{% block pageContent %}
{% include "assiduites/widgets/alert.j2" %}

<div class="pageContent">
    {{minitimeline | safe }}
    <h2>Assiduité de {{sco.etud.html_link_fiche()|safe}}</h2>

    <div class="options">
        <input type="checkbox" id="show_pres" name="show_pres" class="memo"><label for="show_pres">afficher les présences</label>
        <input type="checkbox" name="show_reta" id="show_reta" class="memo"><label for="show_reta">afficher les retards</label>
        <input type="checkbox" name="mode_demi" id="mode_demi" class="memo" checked><label for="mode_demi">mode demi journée</label>
    </div>

    <div class="calendrier">

    </div>
    <div class="annee">
        <span id="label-annee">Année scolaire 2022-2023</span><span id="label-changer" style="margin-left: 5px;">Changer
            année: </span>
        <select name="" id="annee" onchange="setterAnnee(this.value)">
        </select>

        <span id="label-nom">Assiduité de {{sco.etud.nomprenom}}</span>
    </div>

    <div class="help">
        <h3>Calendrier</h3>
        <p>Code couleur</p>
        <ul class="couleurs">
            <li><span title="Vert" class="present demo"></span> &rightarrow; présence de l'étudiant lors de la période
            </li>
            <li><span title="Bleu clair" class="nonwork demo"></span> &rightarrow; la période n'est pas travaillée
            </li>
            <li><span title="Rouge" class="absent demo"></span> &rightarrow; absence de l'étudiant lors de la période
            </li>
            <li><span title="Rose" class="demo color absent est_just"></span> &rightarrow; absence justifiée
            </li>
            <li><span title="Orange" class="retard demo"></span> &rightarrow; retard de l'étudiant lors de la période
            </li>
            <li><span title="Jaune clair" class="demo color retard est_just"></span> &rightarrow; retard justifié
            </li>

            <li><span title="Quart Bleu" class="est_just demo"></span> &rightarrow; la période est couverte par un
                justificatif valide</li>
            <li><span title="Justif. non valide" class="invalide demo"></span> &rightarrow; la période est
                couverte par un justificatif non valide
            </li>
            <li><span title="Justif. en attente" class="attente demo"></span> &rightarrow; la période
                a un justificatif en attente de validation
            </li>
        </ul>


        <p>Vous pouvez passer le curseur sur les jours colorés afin de voir les informations supplémentaires</p>
    </div>
    <ul class="couleurs print">
        <li><span title="Vert" class="present demo"></span> présence
        </li>
        <li><span title="Bleu clair" class="nonwork demo"></span> non travaillé
        </li>
        <li><span title="Rouge" class="absent demo"></span> absence
        </li>
        <li><span title="Rose" class="demo color absent est_just"></span> absence justifiée
        </li>
        <li><span title="Orange" class="retard demo"></span> retard
        </li>
        <li><span title="Jaune clair" class="demo color retard est_just"></span>retard justifié
        </li>
        <li><span title="Quart Bleu" class="est_just demo"></span>
            justificatif valide</li>
        <li><span title="Quart Violet" class="invalide demo"></span> justificatif non valide
        </li>
    </ul>
</div>

<style>
    .help .couleurs {
        grid-template-columns: 2;
        grid-template-rows: auto;
        display: grid;
    }

    .couleurs.print {
        display: none;
    }

    .help .couleurs li:nth-child(odd) {
        grid-column: 1;
        list-style-type: none;
    }

    .help .couleurs li:nth-child(even) {
        grid-column: 2;
        list-style-type: none;
    }

    .color.present {
        background-color: var(--color-present) !important;
    }

    .color.absent {
        background-color: var(--color-absent) !important;
    }

    .color.absent.est_just {
        background-color: var(--color-absent-justi) !important;
    }
    .color.retard {
        background-color: var(--color-retard) !important;
    }

    .color.retard.est_just {
        background-color: var(--color-retard-justi) !important;
    }

    .color.nonwork {
        background-color: var(--color-nonwork) !important;
    }

    .color {
        background-color: var(--color-defaut) !important;
    }

    .pageContent {
        margin-top: 1vh;
        max-width: var(--sco-content-max-width);
    }

    .calendrier {
        display: flex;
        justify-content: space-evenly;
        flex-wrap: wrap;
        border: 1px solid #444;
        border-radius: 12px;
        margin-bottom: 12px;
    }

    .month h3 {
        text-align: center;
    }

    .day,
    .demi .day.color.nonwork {
        text-align: left;
        margin: 2px;
        cursor: default;
        font-size: 13px;
        position: relative;
        font-weight: normal;
        min-width: 6em;
        display: flex;
        justify-content: start;
    }

    .color.est_just.sans_etat::before {
        content: "";
        position: absolute;
        width: 25%;
        height: 100%;
        background-color: var(--color-justi) !important;
        right: 0;
    }

    .color.invalide::before {
        content: "";
        position: absolute;
        width: 25%;
        height: 100%;
        right: 0;
        background-color: var(--color-justi-invalide) !important;
    }
    .color.attente::before,  .color.modifie::before {
        content: "";
        position: absolute;
        width: 25%;
        height: 100%;
        right: 0;
        background: repeating-linear-gradient(
            to bottom,
            var(--color-justi-attente-stripe) 0px,
            var(--color-justi-attente-stripe) 4px,
            var(--color-justi-attente) 4px,
            var(--color-justi-attente) 7px
        )!important;
    }
    .demo.invalide {
        background-color: var(--color-justi-invalide) !important;
    }
    .demo.attente {
        background: repeating-linear-gradient(
            to bottom,
            var(--color-justi-attente-stripe) 0px,
            var(--color-justi-attente-stripe) 4px,
            var(--color-justi-attente) 4px,
            var(--color-justi-attente) 7px
        )!important;
    }

    .demo.est_just {
        background-color: var(--color-justi) !important;
    }


    .demi .day.nonwork>span {
        flex: none;
        border: none;
    }

    .demi .day {
        border-radius: 0;
    }



    .day .dayline {
        position: absolute;
        display: none;
        top: 100%;
        z-index: 50;
        width: max-content;
        height: 75px;
        background-color: #dedede;
        border-radius: 15px;
        padding: 5px;
    }

    .day:hover .dayline {
        display: block;
    }

    .dayline .mini-timeline {
        margin-top: 10%;
    }

    .dayline-title {
        margin: 0;
    }

    .dayline .mini_tick {
        position: absolute;
        text-align: center;
        top: 0;
        transform: translateY(-110%);
        z-index: 50;
    }

    .dayline .mini_tick::after {
        display: block;
        content: "|";
        position: absolute;
        bottom: -69%;
        z-index: 2;
        transform: translateX(200%);
    }

    #label-nom,
    #label-justi {
        display: none;
    }

    .demi .day {
        display: flex;
        justify-content: space-evenly;
    }

    .demi .day>span {
        display: block;
        flex: 1;
        text-align: center;
        z-index: 1;
        width: 100%;
        border: 1px solid #d5d5d5;
        position: relative;
    }

    .demi .day>span:first-of-type {
        width: 3em;
        min-width: 3em;
    }

    .options>* {
        margin-right: 5px;
    }

    .options input {
        margin-right: 6px;
    }

    .options label {
        font-weight: normal;
        margin-right: 16px;
    }

    @media print {

        .couleurs.print {
            display: flex;
            justify-content: space-evenly;
            align-items: center;
        }

        .couleurs.print li {
            list-style-type: none !important;
            -webkit-print-color-adjust: exact !important;
            print-color-adjust: exact !important;
        }

        .day,
        .demi .day.color.color.nonwork {
            min-width: 5em;
            font-size: 11px;
        }

        .demi .day>span:first-of-type {
            width: 2.5em;
            min-width: 2.5em;
        }

        .color {
            -webkit-print-color-adjust: exact !important;
            print-color-adjust: exact !important;
        }

        .day.est_just,
        .demi .day span.est_just {
            background-image: none;

        }

        .day.invalide,
        .demi .day span.invalide {
            background-image: none;
        }

        .demi .day span.est_just::before {
            content: "J";
        }

        .demi .day span.invalide::before {
            content: "JI";
        }

        #sidebar,
        .help,
        h2,
        #annee,
        #label-changer,
        .options {
            display: none;
        }

        #label-nom,
        #label-justi {
            display: inline;
        }

        #gtrcontent {
            margin: 5px;
        }

        .annee {
            display: flex;
            justify-content: space-evenly;
            align-items: center;
        }
    }
</style>

<script>

    const datePivot = "{{scu.get_assiduites_time_config("pivot")}}".split(":").map((el) => Number(el))

    function getDaysBetweenDates(start, end) {
        let now = new Date(start);
        end = new Date(end);
        let dates = [];

        while (now.isBefore(end) || now.isSame(end)) {
            dates.push(now.clone());
            now.add(1, "days");
        }

        return dates;
    }

    function organizeByMonth(dates) {
        let datesByMonth = {};

        dates.forEach((date) => {
            let month = date.toLocaleString('fr-FR', { month: "short" }); // Obtenir le mois

            if (!datesByMonth[month]) {
                datesByMonth[month] = [];
            }

            datesByMonth[month].push(date);
        });

        return datesByMonth;
    }

    function organizeAssiduitiesByDay(datesByMonth, assiduities, justificatifs) {
        let assiduitiesByDay = {};

        Object.keys(datesByMonth).forEach((month) => {
            assiduitiesByDay[month] = {};

            datesByMonth[month].forEach((date) => {
                let dayAssiduities = assiduities.filter((assiduity) => {
                    return new Date(date).isBetween(
                        new Date(assiduity.date_debut).startOf("day"),
                        new Date(assiduity.date_fin).endOf("day"),
                        "[]"
                    )
                });

                let dayJustificatifs = justificatifs.filter((justif) => {
                    return new Date(date).isBetween(
                        new Date(justif.date_debut).startOf("day"),
                        new Date(justif.date_fin).endOf("day"),
                        "[]"
                    )
                });

                assiduitiesByDay[month][date.toLocaleDateString("en-US")] = {
                    assiduites: dayAssiduities,
                    justificatifs: dayJustificatifs
                };
            });
        });

        return assiduitiesByDay;
    }

    function generateCalendar(assiduitiesByDay, nonWorkdays = []) {
        // assiduitiesByDay[month][date] avec date au format m/d/y !!!
        const calendar = document.querySelector('.calendrier')
        const options = getOptions();
        calendar.innerHTML = ""

        const days = {
            1: "Lun",
            2: "Mar",
            3: "Mer",
            4: "Jeu",
            5: "Ven",
            6: "Sam",
            0: "Dim",
        };
        // XXX formats de données très exotiques !
        // XXX assiduitiesByDay["oct."]["10/12/2023"]
        // XXX     Object { assiduites: [], justificatifs: [] }
        Object.keys(assiduitiesByDay).forEach((month) => {
            const monthEl = document.createElement('div')
            monthEl.classList.add("month")
            const title = document.createElement('h3');
            title.textContent = `${month.capitalize()}`;
            monthEl.appendChild(title)

            const daysEl = document.createElement('div')
            daysEl.classList.add('days');
            if (options.mode_demi) daysEl.classList.add("demi");
            Object.keys(assiduitiesByDay[month]).forEach((date) => {
                let dayAssiduities = assiduitiesByDay[month][date].assiduites;
                let dayJustificatifs = assiduitiesByDay[month][date].justificatifs;
                let color = "sans_etat";

                if (dayAssiduities.some((a) => a.etat.toLowerCase() === "absent")) color = "absent";
                else if (dayAssiduities.some((a) => a.etat.toLowerCase() === "retard") && options.show_reta)
                    color = "retard";
                else if (dayAssiduities.some((a) => a.etat.toLowerCase() === "present") && options.show_pres)
                    color = "present";


                let est_just = ""
                if (dayJustificatifs.some((j) => j.etat.toLowerCase() === "valide")) {
                    est_just = "est_just";
                } else if (dayJustificatifs.some((j) => j.etat.toLowerCase() === "attente")) {
                        est_just = "attente";
                } else if (dayJustificatifs.some((j) => j.etat.toLowerCase() === "modifie")) {
                        est_just = "modifie";
                } else if (dayJustificatifs.some((j) => j.etat.toLowerCase() !== "valide")) {
                    est_just = "invalide";
                }
                const momentDate = new Date(date);
                let dayOfMonth = momentDate.getDate();
                let dayOfWeek = momentDate.getDay();
                dayOfWeek = days[dayOfWeek];

                let isNonWorkDayVar = nonWorkdays.includes(dayOfWeek.toLowerCase());
                const day = document.createElement('div');
                day.className = `day`;
                if (isNonWorkDayVar) {
                    color = "nonwork";
                } else if (!options.mode_demi) {
                    day.className = `day ${est_just}`;
                }


                if (options.mode_demi && !isNonWorkDayVar) {

                    est_just = []
                    // affichage n° jour + matin + aprem

                    const span_jour = document.createElement("span")
                    span_jour.textContent = dayOfWeek[0] + dayOfMonth;

                    const span_matin = document.createElement("span");
                    span_matin.classList.add("color");
                    const matin = [new Date(date), new Date(date)]
                    color = "sans_etat"
                    matin[0].setHours(0, 0, 0, 0)
                    matin[1].setHours(...datePivot)



                    const assiduitesMatin = dayAssiduities.filter((el) => {
                        const deb = new Date(el.date_debut);
                        const fin = new Date(el.date_fin);
                        return Date.intersect({ deb: deb, fin: fin }, { deb: matin[0], fin: matin[1] })
                    })
                    const justificatifsMatin = dayJustificatifs.filter((el) => {
                        const deb = new Date(el.date_debut);
                        const fin = new Date(el.date_fin);
                        return Date.intersect({ deb: deb, fin: fin }, { deb: matin[0], fin: matin[1] })
                    })

                    if (assiduitesMatin.some((a) => a.etat.toLowerCase() === "absent")) color = "absent";
                    else if (assiduitesMatin.some((a) => a.etat.toLowerCase() === "retard") && options.show_reta)
                        color = "retard";
                    else if (assiduitesMatin.some((a) => a.etat.toLowerCase() === "present") && options.show_pres)
                        color = "present";

                    if (color != "") {
                        span_matin.classList.add(color);
                    }

                    if (justificatifsMatin.some((j) => j.etat.toLowerCase() === "valide")) {
                        est_just = ["est_just"];
                    } else if (justificatifsMatin.some((j) => j.etat.toLowerCase() === "attente")) {
                        est_just = ["attente"];
                    } else if (justificatifsMatin.some((j) => j.etat.toLowerCase() === "modifie")) {
                        est_just = ["modifie"];
                    }
                    else if (justificatifsMatin.some((j) => j.etat.toLowerCase() !== "valide")) {
                        est_just = ["invalide"];
                    }

                    span_matin.classList.add(...est_just)


                    est_just = []
                    const span_aprem = document.createElement("span");
                    span_aprem.classList.add("color");
                    const aprem = [new Date(date), new Date(date)]
                    color = "sans_etat"
                    aprem[0].setHours(...datePivot)
                    aprem[0].add(1, "seconds")
                    aprem[1].setHours(23, 59, 59)


                    const assiduitesAprem = dayAssiduities.filter((el) => {
                        const deb = new Date(el.date_debut);
                        const fin = new Date(el.date_fin);
                        return Date.intersect({ deb: deb, fin: fin }, { deb: aprem[0], fin: aprem[1] })
                    })

                    const justificatifsAprem = dayJustificatifs.filter((el) => {
                        const deb = new Date(el.date_debut);
                        const fin = new Date(el.date_fin);
                        return Date.intersect({ deb: deb, fin: fin }, { deb: aprem[0], fin: aprem[1] })
                    })

                    if (assiduitesAprem.some((a) => a.etat.toLowerCase() === "absent")) color = "absent";
                    else if (assiduitesAprem.some((a) => a.etat.toLowerCase() === "retard") && options.show_reta)
                        color = "retard";
                    else if (assiduitesAprem.some((a) => a.etat.toLowerCase() === "present") && options.show_pres)
                        color = "present";

                    if (color != "") {
                        span_aprem.classList.add(color);
                    }

                    if (justificatifsAprem.some((j) => j.etat.toLowerCase() === "valide")) {
                        est_just = ["est_just"];
                    } else if (justificatifsAprem.some((j) => j.etat.toLowerCase() === "attente")) {
                        est_just = ["attente"];
                    } else if (justificatifsAprem.some((j) => j.etat.toLowerCase() === "modifie")) {
                        est_just = ["modifie"];
                    } else if (justificatifsAprem.some((j) => j.etat.toLowerCase() !== "valide")) {
                        est_just = ["invalide"];
                    }

                    span_aprem.classList.add(...est_just)

                    day.appendChild(span_jour)
                    day.appendChild(span_matin)
                    day.appendChild(span_aprem)


                } else {
                    day.classList.add("color")
                    if (color != "") {
                        day.classList.add(color);
                    }

                    if (isNonWorkDayVar) {
                        const span_jour = document.createElement("span")
                        span_jour.textContent = dayOfWeek[0] + dayOfMonth;
                        day.appendChild(span_jour);
                    } else {
                        day.textContent = `${dayOfWeek} ${dayOfMonth}`;
                    }


                }


                if (!nonWorkdays.includes(dayOfWeek.toLowerCase()) && dayAssiduities.length > 0) {
                    const cache = document.createElement('div')
                    cache.classList.add('dayline');
                    const title = document.createElement('div')
                    title.className = "dayline-title";

                    title.innerHTML = "<span>Assiduité du </span><br>" + `<span>${formatDate(momentDate)}</span>`;
                    cache.appendChild(title)
                    cache.appendChild(
                        createMiniTimeline(dayAssiduities, date)
                    )
                    day.appendChild(cache)
                }



                daysEl.appendChild(day);
            });
            monthEl.appendChild(daysEl)
            calendar.appendChild(monthEl)
        });

    }

    function getEtudAssiduites(deb, fin, callback = () => { }) {
        const url_api =
            getUrl() +
            `/api/assiduites/${etudid}/query?date_debut=${deb}&date_fin=${fin}`;
        async_get(url_api, (data) => {
            callback(data);
        });
    }

    function getOptions() {
        return {
            "show_pres": document.getElementById("show_pres").checked,
            "show_reta": document.getElementById("show_reta").checked,
            "mode_demi": document.getElementById("mode_demi").checked,
        }
    }

    function getEtudJustificatifs(deb, fin) {
        let list = [];
        const url_api =
            getUrl() +
            `/api/justificatifs/${etudid}/query?date_debut=${deb}&date_fin=${fin}`;
        sync_get(url_api, (data, status) => {
            if (status === "success") {
                list = data;
            }
        });

        return list
    }

    function generate(annee) {
        if (annee < 1999 || annee > 2999) {
            openAlertModal("Année impossible", document.createTextNode("L'année demandé n'existe pas."));
            return;
        }
        const bornes = {
            deb: `${annee}-09-01T00:00`,
            fin: `${annee + 1}-08-31T23:59`
        }

        let assiduities = getEtudAssiduites(bornes.deb, bornes.fin, (data) => {
            let dates = getDaysBetweenDates(bornes.deb, bornes.fin);
            let datesByMonth = organizeByMonth(dates);
            const justifs = getEtudJustificatifs(bornes.deb, bornes.fin);
            let assiduitiesByDay = organizeAssiduitiesByDay(datesByMonth, data, justifs);
            generateCalendar(assiduitiesByDay, nonwork);
        });

    }

    function setterAnnee(annee) {
        annee = parseInt(annee);
        document.querySelector('.annee #label-annee').textContent = `Année scolaire ${annee}-${annee + 1}`
        generate(annee)

    }

    const defAnnee = {{ annee }}
    let annees = {{ annees | safe }}
    annees = annees.filter((x, i) => annees.indexOf(x) === i)
    const etudid = {{ sco.etud.id }};
    const nonwork = [{{ nonworkdays | safe }}];
    window.onload = () => {
        const select = document.querySelector('#annee');
        annees.forEach((a) => {
            const opt = document.createElement("option");
            opt.value = a + "",
                opt.textContent = `${a} - ${a + 1}`;
            if (a === defAnnee) {
                opt.selected = true;
            }
            select.appendChild(opt)
        })

        document.querySelectorAll(".options input").forEach((e) => {
            e.addEventListener("click", () => {
                setterAnnee(select.value)
            })
        })
        setterAnnee(defAnnee)
    };


    function isCalendrier() { return true }

    /* --- Mémorisation des checkbox ---- */
    document.querySelectorAll('input[type="checkbox"].memo').forEach(checkbox => {
        checkbox.addEventListener('change', function() {
            localStorage.setItem(this.id, this.checked);
    });
    // Load the saved state
    document.querySelectorAll('input[type="checkbox"].memo').forEach(checkbox => {
        const checked = localStorage.getItem(checkbox.id) === 'true';
        checkbox.checked = checked;
    });
});
</script>
{% endblock pageContent %}
