// calendar.js

document.addEventListener('DOMContentLoaded', async function () {
    const months_short = [0, 'Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'];
    const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstg', 'Freitag', 'Samstag', 'Sonntag'];
    const url = '../DB4js.php';
    const default_dauer = 90;                                   // Standardführung dauert 90min
    let fuehrungszeiten;
    let isedit;
    let entryInfo;


    // Von der Datenbank Werte abholen
    // Param:
    //      body: Object mit cmd und param
    // Return:
    //      angeforderte Daten als JSON
        const fetchFromDbase = async (body) => {
            const response = await fetch(url, {
                method: 'POST',
                headers: {'Content-Type': 'application/js'},
                body: JSON.stringify(body)
            });
            return await response.json();
        }


    // In die Datenbank Werte eintragen
    // Param:
    //      body: Object mit cmd und param
    // Return:
    //      angeforderte Daten als JSON
        const putToDbase = async (body) => {
            const response = await fetch(url, {
                method: 'POST',
                headers: {'Content-Type': 'application/js'},
                body: JSON.stringify(body)
            });
            return await response.json();
        }


    // Die Daten der BEOs, die in einem Führungsteam sind, abholen
    // Params: keine
    // Retur:
    //      beos direkt gesetzt
    async function getBEOs() {
        let data = await fetchFromDbase({cmd: 'GET_BEOS', id: 'all', onlyguides: 'true'});
        return data;
    }

    $('#versn').html("Version: " + VERSION + ' vom ' + VDATE)

    let beos = await getBEOs();


    // FullCalendar aufrufen und mit den Optionen versorgen
    const calendarEl = document.getElementById('calendar');
    let calendar = new FullCalendar.Calendar(calendarEl, {
        themeSystem: 'bootstrap',
        aspectRatio: 1.75,
        locale: 'de',
        editable: true,
        selectable: true,
        businessHours: {
            daysOfWeek: [1, 2, 3, 4, 5],
            startTime: '00:00',
            endTime: '23.59'
        },
        nextDayThreshold: '00:30:00',
        eventTimeFormat: {
            hour: '2-digit',
            minute: '2-digit',
            meridiem: false
        },
        schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
        customButtons: {
            anleitButton: {
                text: "Anleitung",
                click: function() {
                    showAnleitung();
                }
            }
        },
        headerToolbar: {
            start: 'anleitButton',
            center: 'title',
            end: 'today prev next'
        },
        firstDay: 1,
        buttonText: {
            today: 'heute'
        },
        dayMaxEvents: true, // allow "more" link when too many events
        eventSources: [
            {
                events: async function (info, success, failure) {
                    try {
                        let fdates = await getFdates(info.start, info.end, beos);
                        success(fdates);
                    } catch (err) {
                        console.log("Fehler gekommen:", err);
                        failure(err);
                    }
                },
                color: '#e3e839',
                borderColor: '#e3e839',
                textColor: 'black',
            },
            {
                events: async function (info, success, failure) {
                    try {
                        let fdates = getSundays(info.start);
                        success(fdates);
                    } catch (err) {
                        console.log("Fehler gekommen:", err);
                        failure(err);
                    }
                },
                color: '#e3e839',
                borderColor: '#e3e839',
                textColor: 'black',
            },
            {
                events: async function (info, success, failure) {
                    try {
                        let fdates = await getCaldates(info.start, info.end);
                        success(fdates);
                    } catch (err) {
                        console.log("Fehler gekommen:", err);
                        failure(err);
                    }
                },
            },
            {
                events: async function (info, success, failure) {
                    try {
                        let fdates = await getHolidays(info.start, info.end);
                        success(fdates);
                    } catch (err) {
                        console.log("Fehler gekommen:", err);
                        failure(err);
                    }
                },
                color: '#AAA',
                borderColor: '#AAA',
                textColor: 'black',
            }
        ],
        eventDisplay: 'block',
        dateClick: function (info) {
            entryInfo = info.event;
            console.log("Dateclick ausgeführt");
            isedit = false;
            fillModal(info.date, null);
            $('#myModal .modal-title').text('Neuer Eintrag');
            $('#myModal').modal();
        },
        /*
        eventMouseEnter: async function (info) {
            isedit = true;
            entryInfo = info.event;
            let start = entryInfo.start;
            const holiday = await checkInHoliday(start);
            if (holiday == -1) {
                $(info.el).popover({
                    container: 'body',
                    title: entryInfo.title,
                    content: (entryInfo._def.extendedProps.description !== undefined) ? getFuehrungsInfo(entryInfo) : getRegularInfo(entryInfo),
                    trigger: 'hover',
                    placement: 'auto',
                    html: true

                });
                $(info.el).popover('show');
            }
        },
        */
        eventClick: function (info) {
            isedit = true;
            entryInfo = info.event;
            showViewModal(entryInfo);
        },
    });
// *** Ende der Kalender-optionen

    calendar.render();

// ************
// Button-Event-Handler für die Dialog-Boxen
// ************

    $('#btn_delete').click(function () {
        btnDeleteClicked(true);
    });

    $('#btn_edit').click(function () {
        btnEditClicked();
    });

    $('#btn_saveentry').click(function () {
        btnSaveClicked();
    });


// 'Speichern' geklicked:
    async function btnSaveClicked() {
        let ready = await saveEntry();
        if (isedit && ready) {
            await deleteEntry(entryInfo._def.publicId, false);
        }
        calendar.refetchEvents();
        console.log("gelöscht bei Edit");
    }

    // 'Löschen' geklicked
    async function btnDeleteClicked(abfrage) {
        $('#viewModal').modal('hide');
        await deleteEntry(entryInfo._def.publicId, abfrage);
    }

    async function deleteEntry(id, abfrage) {
        if (abfrage) {
            if (!confirm('Wirklich löschen?')) {
                return;
            }
        }
        // let event = calendar.getEventById(id);
        // event.remove();
        $('#txtTitle').val('');
        $('#txtBeschr').val('');
        let ret = await putToDbase({cmd: 'DEL_CALENTRY', id: id});
        if (ret != true) {
            alert(`Fehler beim Löschen des Eintrages !`);
        }
        calendar.refetchEvents();
    }


    // 'Ändern' geklicked:
    async function btnEditClicked() {
        $('#viewModal').modal('hide');
        $('#myModal .modal-title').text('Eintrag ändern');
        $('#myModal').modal();
        fillModal(entryInfo.start, entryInfo.end);
        console.log(entryInfo.title, entryInfo._def.extendedProps.description);
        $('#txtTitle').val(entryInfo.title);
        $('#txtBeschr').val(entryInfo._def.extendedProps.description);
    }


// Reaktion auf den 'Sichern'-Knopf
// Den Eintrag zusammen bauen, dann in die Datenbank eintragen und das
// Fenster wieder löschen
    const saveEntry = async () => {
        if ($('#txtTitle').val() == '') {
            alert("Es muss ein Titel eingebeben werden!");
            return false;
        }
        let entry = {};
        entry.title = $('#txtTitle').val();
        entry.description = $('#txtBeschr').val();
        entry.start = $('#st_date_year option:selected').text() + '-';
        entry.start += $('#st_date_month option:selected').val() + '-';
        entry.start += $('#st_date_day option:selected').text() + 'T';
        entry.start += $('#st_date_hours option:selected').text() + ':';
        entry.start += $('#st_date_minutes option:selected').text();
        entry.end = $('#end_date_year option:selected').text() + '-';
        entry.end += $('#end_date_month option:selected').val() + '-';
        entry.end += $('#end_date_day option:selected').text() + 'T';
        entry.end += $('#end_date_hours option:selected').text() + ':';
        entry.end += $('#end_date_minutes option:selected').text();
        if (!isedit) {
            $('#txtTitle').val('');
            $('#txtBeschr').val('');
        }
        $('#myModal').modal('hide');
        let ret = await putToDbase({cmd: 'PUT_CALENTRY', data: entry});
        return ret;
    }

// ********************
    // Ende Button-Event-Handler
// ********************


// Die Startzeit des dritten (der liegt gesichert im aktuellen Monat)
// Regelführungstermins des Monats finden
// Params:
//      keine
// Return:
//      entweder die Startzeit, falls gefunden oder aber 20 [Uhr]
    function getFuehrungszeitZeit() {
        if (fuehrungszeiten[3].start !== undefined) {
            let st = moment(fuehrungszeiten[3].start);
            return st.hour();
        } else {
            return 20;
        }
    }


// das Dialog-Fenster mit den Datums/Zeit-Optionen füllen
// Params:
//      st_seldate      gewähltes Startdatum
//      end_seldate     gewähltes Enddatum (oder leer => null)
// Return:
//      nix
    function fillModal(st_seldate, end_seldate) {
        let start, end;
        if (isedit) {
            start = moment(st_seldate);
            end = moment(end_seldate);
        } else {
            start = moment(st_seldate);
            start.hour(getFuehrungszeitZeit());
            end = moment(st_seldate);
            end.hour(getFuehrungszeitZeit());
            end = end.add(default_dauer, 'm');
            $('#txtTitle').val('');
            $('#txtBeschr').val('');
        }
        $('#st_date_day #end_date_day').html('');
        $('#end_date_day').html('');
        for (let i = 1; i <= 31; i++) {
            $('#st_date_day').append(`<option ${start.date() == i ? 'selected' : ''}>${i}</option>`);
            $('#end_date_day').append(`<option ${end.date() == i ? 'selected' : ''}>${i}</option>`);
        }
        $('#st_date_month #end_date_month').html('');
        $('#end_date_month').html('');
        for (let i = 1; i <= 12; i++) {
            $('#st_date_month').append(`<option value=${i} ${(start.month() + 1) == i ? 'selected' : ''}>${months_short[i]}</option>`);
            $('#end_date_month').append(`<option value=${i} ${(end.month() + 1) == i ? 'selected' : ''}>${months_short[i]}</option>`);
        }
        $('#st_date_year #end_date_year').html('');
        $('#end_date_year').html('');
        for (let i = 2020; i <= 2030; i++) {
            $('#st_date_year').append(`<option ${start.year() == i ? 'selected' : ''}>${i}</option>`);
            $('#end_date_year').append(`<option ${end.year() == i ? 'selected' : ''}>${i}</option>`);
        }
        $('#st_date_hours').html('');
        $('#end_date_hours').html('');
        for (let i = 0; i <= 23; i++) {
            $('#st_date_hours').append(`<option ${start.hour() == i ? 'selected' : ''}>${("0" + i).slice(-2)}</option>`);
            $('#end_date_hours').append(`<option ${end.hour() == i ? 'selected' : ''}>${("0" + i).slice(-2)}</option>`);
        }
        $('#st_date_minutes').html('');
        $('#end_date_minutes').html('');
        for (let i = 0; i <= 50; i += 10) {
            $('#st_date_minutes').append(`<option ${start.minute() == i ? 'selected' : ''}>${("0" + i).slice(-2)}</option>`);
            $('#end_date_minutes').append(`<option ${end.minute() == i ? 'selected' : ''}>${("0" + i).slice(-2)}</option>`);
        }
    }

// Aus der BEOs-Datenbank die namen und die Kürzel der
// für den übergebenen Führungstag aktiven BEOs
// Params:
//      beos        Array der Daten der BEOs
//      data        Objekt mit dem Führungstag
// Return:
//      Objekt mit den Kürzeln und den Namen der aktiven BEOs
    function checkGroupinBeos(beos, data) {
        let kurz = "";
        let name = "";
        for (let b of beos) {
            let grps = b.gruppe.split(',');
            for (let i in grps) {
                if (data.title == grps[i]) {
                    kurz += b.kürzel + ',';
                    name += `${b.vorname} ${b.name}<br />`;
                }
            }
        }
        return {k: kurz.slice(0, -1), n: name};
    }


// Aus der Datenbank die Regel-Führungstage des Monat holen und die
// aktiven BEOs dazu eintragen
// Params:
//      start           Startdatum zu Suche in der DB
//      end             Endedatum dazu
//      beos            Array mit den BEOs daten
// Retur:
//      Array mit den Regel-Führungszeiten des Monats mit den BEOs
    async function getFdates(start, end, beos) {
        // Zuerst die regelmäßigen Führungen hole
        fuehrungszeiten = await fetchFromDbase({cmd: 'GET_FDATES', start: start, end: end});
        for (let i = 0; i < fuehrungszeiten.length; i++) {
            let start = moment(fuehrungszeiten[i].start);
            start.add(fuehrungszeiten[i].uhr,'h')
            fuehrungszeiten[i].start = moment(start).format()
            let kurz = checkGroupinBeos(beos, fuehrungszeiten[i]);
            if (kurz.k != "") {
                fuehrungszeiten[i].title += " " + kurz.k;
                fuehrungszeiten[i].namen = kurz.n;
            }
        }
        return fuehrungszeiten;
    }

// Aus der Datenbank die eingetragenen Führungen  für den laufenden Monat holen
// Params:
//      start, ende         Start- und Endezeitpunk für die Suche in der DB
// Return:
//      Array mit Führungen des laufenden Monats
    async function getCaldates(start, end) {
        return await fetchFromDbase({cmd: 'GET_CALENTRIES', start: start, end: end});
    }

// Prüfen, ob das übergeben Datum in der Feiertags-Liste enthalten ist
// Params:
//      date            das zu prüfende Datum
//
// Return:
//      true: das Datum ist ein Feiertag
//      false: es ist keiner
    async function checkInHoliday(date) {
        const feiertage = await getHolidays(date)
        let month = (date.getMonth()+1) <= 9 ? "0" + (date.getMonth()+1) : (date.getMonth()+1)
        let day = date.getDate() <= 9 ? "0"+date.getDate() : date.getDate()
        const datum = date.getFullYear() + '-' + month + "-" + day;
        return feiertage.findIndex(x => x.start == datum);
    }


// Die Feiertage in Baden-Württemberg von einer API via HTTP abholen
// Params:
//      start, end       Jahre, für das die Feiertage geholt werden
//      ACHTUNG: es werden max. 2 Jahre geholt (start und end), da der
//              Kalender max. 2 folgende Jahre anfordert.
// Return:
//      Array mit den Feiertagen
    async function getHolidays(start, end) {
        let data = [];
        let startyear = moment(start).year();
        let endyear = moment(end).year();
        let response = await fetch('https://feiertage-api.de/api/?jahr=' + startyear + '&nur_land=BW');
        let holidays = await response.json();
        for (const [k, v] of Object.entries(holidays)) {
            if(k == "Ostermontag") {
                data.push({start: moment(v.datum).subtract(1,'days').format("YYYY-MM-DD"), title: "Ostersonntag"});
            }
            if(k == "Pfingstmontag") {
                data.push({start: moment(v.datum).subtract(1,'days').format("YYYY-MM-DD"), title: "Pfingstsonntag"});
            }
            data.push({start: v.datum, title: k});
        }
        if (startyear != endyear) {
            let response = await fetch('https://feiertage-api.de/api/?jahr=' + endyear + '&nur_land=BW');
            let holidays = await response.json();
            for (const [k, v] of Object.entries(holidays)) {
                data.push({start: v.datum, title: k});
            }
        }
        return data;
    }

// die ersten Sonntage des Monates im laufenden Jahr finden
// Params:
//      year: das Jahr, für das die Sonntage gesucht werden
// Return:
//      Array mit den Sonntagen
    function getSundays(dt) {
        let year = moment(dt).year();
        const cm = moment(dt).month()
        if (moment(dt).month() == 11) {
            year += 1;
        }
        let data = [];
        for (let i = 1; i <= 12; i++) {
            let d = moment(year + '-' + i + '-01');
            let w = d.isoWeekday();
            let dt = ''
            if (w == 7) {
                dt = d.format('YYYY-MM-DD');
            } else {
                dt = d.add(7 - w, 'd').format('YYYY-MM-DD')
            }
            data.push({start: dt + 'T11:00:00', uhr: 11, title: 'Sonnenführung' })
        }
        return data;
    }


// Anzeige des Dialogfensters zum Ändern/Löschen einer Führung
//
// Dieses Dialogfenster wird nur aufgerufen, wenn auf eine händisch
// eingetragene Führung geklickt wird (nicht bei Regeleführungen).
// Params:
//      entryInfo           Daten des geklickten Eintrages
// Return:
//      nix
    function showViewModal(entryInfo) {
        let str
        $('#viewModal .modal-title').text(entryInfo.title);
        if (entryInfo._def.extendedProps.description !== undefined) { // Führungs-Eintrag
            str = getFuehrungsInfo(entryInfo);
            $('#btn_delete').show()
            $('#btn_edit').show()
        } else {
            str = getRegularInfo(entryInfo)
            $('#btn_delete').hide()
            $('#btn_edit').hide()
        }
        $('#viewModal .viewdesc').html(str);
        $('#viewModal').modal();
    }


// Informationen einer Regelführung für das Popup zusammenbauen
    function getRegularInfo(entryInfo) {
        let curDate = moment(entryInfo.start).format('YYYYMMDD');
        let besucher = entryInfo._def.extendedProps.count;
        if (besucher == null) { besucher = "0"}
        besucher = parseInt(besucher)
        let wtg = moment(entryInfo.start).isoWeekday();
        let nbr = entryInfo.title.split(' ');
        let str = `<h6>${weekdays[wtg - 1]}s-Team ${nbr[1]}</h6>`;
        str += `<div id="beonamen">${entryInfo._def.extendedProps.namen}</div>`;
        let btxt = besucher !=  0 ? `<strong>${besucher}</strong> angemeldete Besucher` : 'Keine Anmeldungen';
        str += btxt;
        str += `<br />Von ${moment(entryInfo.start).format("HH:mm")} Uhr bis: ${moment(entryInfo.start).add(default_dauer, 'm').format("HH:mm")} Uhr`;
        return str;
    }


// Informationen für eine händisch eingetragene Führung zusammenbauen.
// Wird bei dem Popup und bei dem Ändern/löschen verwendent
    function getFuehrungsInfo(entryInfo) {
        let str = entryInfo._def.extendedProps.description;
        str += `<br /><br />Start: ${moment(entryInfo.start).format("YYYY-MM-DD  HH:mm")} Uhr <br />Ende: ${moment(entryInfo.end).format("YYYY-MM-DD  HH:mm")} Uhr`;
        return str;
    }


    function showAnleitung() {
        console.log("Anleitung geklicked");
        $('.viewAnleitung').load("docs/Anleitung.html",function() {
            $('#infoModal').modal({show:true, focus:true});
        });
    };


});  // Ende document.addEventListener()

