<script>
    /**
     * Transformation d'une date de début en position sur la timeline
     * @param {String} start
     * @returns {String} un déplacement par rapport à la gauche en %
     */
    function getLeftPosition(start) {
        const startTime = new Date(start);
        const startMins = (startTime.getHours() - 8) * 60 + startTime.getMinutes();
        return (startMins / (18 * 60 - 8 * 60)) * 100 + "%";
    }
    /**
    * Ajustement de l'espacement vertical entre les assiduités superposées
    * @param {HTMLElement} container le conteneur des assiduités
    * @param {String} start la date début de l'assiduité à placer
    * @param {String} end la date de fin de l'assiduité à placer
    * @returns {String} La position en px
    */
    function getTopPosition(container, start, end) {
        const overlaps = (a, b) => {
            return a.start < b.end && a.end > b.start;
        };

        const startTime = new Date(start);
        const endTime = new Date(end);
        const assiduiteDuration = { start: startTime, end: endTime };

        let position = 0;
        let hasOverlap = true;

        while (hasOverlap) {
            hasOverlap = false;
            Array.from(container.children).some((el) => {
                const elStart = new Date(el.getAttribute("data-start"));
                const elEnd = new Date(el.getAttribute("data-end"));
                const elDuration = { start: elStart, end: elEnd };

                if (overlaps(assiduiteDuration, elDuration)) {
                    position += 25; // Pour ajuster l'espacement vertical entre les assiduités superposées
                    hasOverlap = true;
                    return true;
                }
                return false;
            });
        }
        return position + "px";
    }

    /**
     * Transformation d'un état en couleur
     * @param {String} state l'état
     * @returns {String} la couleur correspondant à l'état
     */
    function getColor(state) {
        switch (state) {
            case "PRESENT":
                return "var(--color-present)";
            case "ABSENT":
                return "var(--color-absent)";
            case "RETARD":
                return "var(--color-retard)";
            default:
                return "var(--color-defaut-dark)";
        }
    }

    /**
    * Calcule de la largeur de l'assiduité sur la timeline
    * @param {String} start date iso de début
    * @param {String} end date iso de fin
    * @returns {String} la taille en %
    */
    function getWidth(start, end) {
        const startTime = new Date(start);
        const endTime = new Date(end);

        const duration = (endTime - startTime) / 1000 / 60;

        const percent = (duration / (18 * 60 - 8 * 60)) * 100

        if (percent > 100) {
            console.log(start, end);
            console.log(startTime, endTime)
        }

        return percent + "%";
    }

    class ConflitResolver {
        constructor(assiduitesList, conflictPeriod, interval) {
            this.list = assiduitesList;
            this.conflictPeriod = conflictPeriod;
            this.interval = interval;
            this.selectedAssiduite = null;

            this.element = undefined;

            this.callbacks = {
                delete: () => { },
                split: () => { },
                edit: () => { },
            }
        }

        refresh(assiduitesList, periode) {
            this.list = assiduitesList;
            if (periode) {
                this.conflictPeriod = periode;
            }

            this.render()

        }

        selectAssiduite() {

        }

        open() {
            const html = `
                        <div id="myModal" class="modal">
                    <div class="modal-content">
                        <span class="close">&times;</span>
                        <h2>Veuillez régler le conflit pour poursuivre</h2>
                        <!-- Ajout de la frise chronologique -->
                        <div class="modal-timeline">
                            <div class="time-labels"></div>
                            <div class="assiduites-container"></div>
                        </div>

                        <div class="action-buttons">
                            <button id="finish" class="btnPrompt">Quitter</button>
                            <button id="delete" class="btnPrompt" disabled>Supprimer</button>
                            <button id="split" class="btnPrompt" disabled>Séparer</button>
                            <button id="edit" class="btnPrompt" disabled>Modifier l'état</button>
                        </div>
                    </div>

                    <div class="modal-assiduite-content">
                        <h2>Information de l'assiduité sélectionnée</h2>
                        <div class="infos">
                            <p>Assiduite id : <span id="modal-assiduite-id">A</span></p>
                            <p>Etat : <span id="modal-assiduite-etat">B</span></p>
                            <p>Date de début : <span id="modal-assiduite-deb">C</span></p>
                            <p>Date de fin: <span id="modal-assiduite-fin">D</span></p>
                            <p>Module : <span id="modal-assiduite-module">E</span></p>
                            <p><span id="modal-assiduite-user">F</span></p>
                        </div>
                    </div>
                </div>
            `;

            document.body.insertAdjacentHTML("afterbegin", html);
            this.element = document.getElementById('myModal');
            this.deleteBtn = document.querySelector('#myModal #delete');
            this.editBtn = document.querySelector('#myModal #edit');
            this.splitBtn = document.querySelector('#myModal #split');
            this.deleteBtn.addEventListener('click', () => { this.deleteAssiduiteModal() });
            this.editBtn.addEventListener('click', () => { this.editAssiduiteModal() });
            this.splitBtn.addEventListener('click', () => { this.splitAssiduiteModal() });
            document.querySelector("#myModal #finish").addEventListener('click', () => { this.close() })

            document.querySelector('#myModal .close').addEventListener('click', () => { this.close() })

            this.render()
        }



        close() {
            if (this.element) {
                this.element.remove()
            }
        }

        /**
        * Sélection d'une assiduité sur la timeline
        * @param {Assiduité} assiduite l'assiduité sélectionnée
        */
        selectAssiduite(assiduite) {
            // Désélectionner l'assiduité précédemment sélectionnée
            if (this.selectedAssiduite) {
                const prevSelectedEl = document.querySelector(
                    `.assiduite[data-id="${this.selectedAssiduite.assiduite_id}"]`
                );
                if (prevSelectedEl) {
                    prevSelectedEl.classList.remove("selected");
                }
            }

            // Sélectionner la nouvelle assiduité
            this.selectedAssiduite = assiduite;
            const selectedEl = document.querySelector(
                `.assiduite[data-id="${assiduite.assiduite_id}"]`
            );
            if (selectedEl) {
                selectedEl.classList.add("selected");
            }

            //Mise à jour de la partie information du modal
            const selectedModal = document.querySelector(".modal-assiduite-content");

            selectedModal.classList.add("show");

            document.getElementById("modal-assiduite-id").textContent =
                assiduite.assiduite_id;
            document.getElementById(
                "modal-assiduite-user"
            ).textContent = `saisie le ${formatDateModal(
                assiduite.entry_date,
                "à"
            )} \npar ${assiduite.user_id}`;
            document.getElementById("modal-assiduite-module").textContent =
                assiduite.moduleimpl_id;
            document.getElementById("modal-assiduite-deb").textContent = formatDateModal(
                assiduite.date_debut
            );
            document.getElementById("modal-assiduite-fin").textContent = formatDateModal(
                assiduite.date_fin
            );
            document.getElementById("modal-assiduite-etat").textContent =
                assiduite.etat.capitalize();

            //Activation des boutons d'actions de conflit
            this.deleteBtn.disabled = false;
            this.splitBtn.disabled = false;
            this.editBtn.disabled = false;
        }
        /**
        * Suppression de l'assiduité sélectionnée
        */
        deleteAssiduiteModal() {
            if (!this.selectedAssiduite) return;
            deleteAssiduite(this.selectedAssiduite.assiduite_id);

            this.callbacks.delete(this.selectedAssiduite)

            this.refresh(assiduites[this.selectedAssiduite.etudid]);

            // Désélection de l'assiduité
            this.resetSelection();
        }

        /**
        * Division d'une assiduité
        */
        splitAssiduiteModal() {
            //Préparation du prompt
            const htmlPrompt = `<legend>Entrez l'heure de séparation (HH:mm) :</legend>
            <input type="time" id="promptTime" name="appt"
                min="08:00" max="18:00" required>`;

            const fieldSet = document.createElement("fieldset");
            fieldSet.classList.add("fieldsplit");
            fieldSet.innerHTML = htmlPrompt;

            //Callback de division
            const success = () => {
                const separatorTime = document.getElementById("promptTime").value;
                const dateString =
                    getDate().format("YYYY-MM-DD") + `T${separatorTime}`;
                const separtorDate = new Date(dateString);

                const assiduite_debut = new Date(this.selectedAssiduite.date_debut);
                const assiduite_fin = new Date(this.selectedAssiduite.date_fin);

                if (
                    separtorDate.isAfter(assiduite_debut) &&
                    separtorDate.isBefore(assiduite_fin)
                ) {
                    const assiduite_avant = {
                        etat: this.selectedAssiduite.etat,
                        date_debut: assiduite_debut.toFakeIso(),
                        date_fin: separtorDate.toFakeIso(),
                    };

                    const assiduite_apres = {
                        etat: this.selectedAssiduite.etat,
                        date_debut: separtorDate.toFakeIso(),
                        date_fin: assiduite_fin.toFakeIso(),
                    };

                    if (this.selectedAssiduite.moduleimpl_id) {
                        assiduite_apres["moduleimpl_id"] = this.selectedAssiduite.moduleimpl_id;
                        assiduite_avant["moduleimpl_id"] = this.selectedAssiduite.moduleimpl_id;
                    }

                    deleteAssiduite(this.selectedAssiduite.assiduite_id);

                    const path = getUrl() + `/api/assiduite/${this.selectedAssiduite.etudid}/create`;
                    sync_post(
                        path,
                        [assiduite_avant, assiduite_apres],
                        (data, status) => {
                            //success
                        },
                        (data, status) => {
                            //error
                            console.error(data, status);
                            errorAlert();
                        }
                    );

                    this.callbacks.split(this.selectedAssiduite)
                    this.refresh(assiduites[this.selectedAssiduite.etudid]);
                    this.resetSelection();
                } else {
                    const att = document.createTextNode(
                        "L'heure de séparation doit être compris dans la période de l'assiduité sélectionnée."
                    );

                    openAlertModal("Attention", att, "", "var(--color-warning))");
                }
            };

            openPromptModal("Séparation de l'assiduité sélectionnée", fieldSet, success, () => { }, "var(--color-present)");
        }

        /**
        * Modification d'une assiduité conflictuelle
        */
        editAssiduiteModal() {
            if (!this.selectedAssiduite) return;

            //Préparation du modal d'édition
            const htmlPrompt = `<legend>Entrez l'état de l'assiduité :</legend>
            <select name="promptSelect" id="promptSelect" required>
                <option value="">Choissez l'état</option>
                <option value="present">Présent</option>
                <option value="retard">En Retard</option>
                <option value="absent">Absent</option>
            </select>`;

            const fieldSet = document.createElement("fieldset");
            fieldSet.classList.add("fieldsplit");
            fieldSet.innerHTML = htmlPrompt;

            //Callback d'action d'édition
            const success = () => {
                const newState = document.getElementById("promptSelect").value;
                if (!["present", "absent", "retard"].includes(newState.toLowerCase())) {
                    const att = document.createTextNode(
                        "L'état doit être 'present', 'absent' ou 'retard'."
                    );
                    openAlertModal("Attention", att, "", "var(--color-warning)");
                    return;
                }

                // Actualiser l'affichage

                editAssiduite(this.selectedAssiduite.assiduite_id, newState, [this.selectedAssiduite]);
                this.callbacks.edit(this.selectedAssiduite)
                this.refresh(assiduites[this.selectedAssiduite.etudid]);

                // Désélection de l'assiduité
                this.resetSelection();
            };

            //Affichage du prompt
            openPromptModal("Modification de l'état de l'assiduité sélectionnée", fieldSet, success, () => { }, "var(--color-present)");
        }

        /**
        * Génération du modal
        */
        render() {
            const timeLabels = document.querySelector(".time-labels");
            const assiduitesContainer = document.querySelector(".assiduites-container");

            timeLabels.innerHTML = "";
            assiduitesContainer.innerHTML = '<div class="assiduite-special"></div>';

            // Ajout des labels d'heure sur la frise chronologique
            // TODO permettre la modification des bornes (8 et 18)
            for (let i = 8; i <= 18; i++) {
                const timeLabel = document.createElement("div");
                timeLabel.className = "time-label";
                timeLabel.textContent = i < 10 ? `0${i}:00` : `${i}:00`;
                timeLabels.appendChild(timeLabel);
            }

            //Placement de la période conflictuelle sur la timeline
            const specialAssiduiteEl = document.querySelector(".assiduite-special");

            specialAssiduiteEl.style.width = getWidth(
                this.conflictPeriod.deb,
                this.conflictPeriod.fin
            );
            specialAssiduiteEl.style.left = getLeftPosition(this.conflictPeriod.deb);
            specialAssiduiteEl.style.top = "0";
            specialAssiduiteEl.style.zIndex = "0"; // Place l'assiduité spéciale en arrière-plan
            assiduitesContainer.appendChild(specialAssiduiteEl);



            //Placement des assiduités sur la timeline
            this.list.forEach((assiduite) => {
                const period = {
                    deb: new Date(assiduite.date_debut),
                    fin: new Date(assiduite.date_fin),
                };
                if (!hasTimeConflict(period, this.interval)) {
                    return;
                }
                const el = document.createElement("div");
                el.className = "assiduite";
                el.style.backgroundColor = getColor(assiduite.etat);


                el.style.width = getWidth(assiduite.date_debut, assiduite.date_fin);
                el.style.left = getLeftPosition(assiduite.date_debut);
                el.style.top = "10px";
                el.setAttribute("data-id", assiduite.assiduite_id);
                el.addEventListener("click", () => this.selectAssiduite(assiduite));

                // Ajout des informations dans la visualisation d'une assiduité
                const infoContainer = document.createElement("div");
                infoContainer.className = "assiduite-info";

                const idDiv = document.createElement("div");
                idDiv.className = "assiduite-id";
                idDiv.textContent = `ID: ${assiduite.assiduite_id}`;
                infoContainer.appendChild(idDiv);

                const periodDivDeb = document.createElement("div");
                periodDivDeb.className = "assiduite-period";
                periodDivDeb.textContent = `${formatDateModal(assiduite.date_debut)}`;
                infoContainer.appendChild(periodDivDeb);
                const periodDivFin = document.createElement("div");
                periodDivFin.className = "assiduite-period";
                periodDivFin.textContent = `${formatDateModal(assiduite.date_fin)}`;
                infoContainer.appendChild(periodDivFin);

                const stateDiv = document.createElement("div");
                stateDiv.className = "assiduite-state";
                stateDiv.textContent = `État: ${assiduite.etat.capitalize()}`;
                infoContainer.appendChild(stateDiv);

                const userIdDiv = document.createElement("div");
                userIdDiv.className = "assiduite-user_id";
                userIdDiv.textContent = `saisie le ${formatDateModal(
                    assiduite.entry_date,
                    "à"
                )} \npar ${assiduite.user_id}`;
                infoContainer.appendChild(userIdDiv);

                el.appendChild(infoContainer);
                assiduitesContainer.appendChild(el);
            });
        }
        /**
        * Remise à zéro de la sélection
        * Désactivation des boutons d'actions de conflit
        */
        resetSelection() {
            this.selectedAssiduite = null;
            this.deleteBtn.disabled = true;
            this.splitBtn.disabled = true;
            this.editBtn.disabled = true;
        }
    }
</script>