/*
Deal with the shift exchanges or shift registrations for ftop partners
  or ABCD partners who need to catch-up for a missed shift.

(ftop = volant; ABCD = inscrit à un créneau)
*/

var optDate = {weekday: "long", year: "numeric", month: "long", day: "numeric"};
var listeShiftPartner =[];
var listStates = {
    not_concerned: "Non concerné",
    up_to_date:" A jour ",
    alert:"Alerte",
    exempted:"Exempté",
    delay:"Délai (extension en cours)",
    suspended:"Suspendu(e)",
    unsubscribed:"Désinscrit",
    unpayed: "Impayé"
};

var limitDate = null,
    dp = null,
    lastY = null,
    loaded_events = [],
    make_up_nb = 0,
    non_regular_shifts = [],
    can_make_exchange = false,
    can_add_shift = false,
    extra_info = $('#templates .extra_info').html();


// Init Dom for member's shifts
function iniListShift(listeShift, echange) {
    if (echange) {
        $('#shifts').html("");
        listeShift.forEach(function f(shift) {
            var dateStart = new Date(shift.date_begin);

            monshift = '<div class="shift_list_item"><label> <input type="checkbox" name = "shiftRadio" value="' + shift.id + '"" /> <span class="shift_booked">' + dateStart.toLocaleDateString("fr-fr", optDate) + " --- " + dateStart.toLocaleTimeString("fr-fr") + '</span></label></div>';
            $('#shifts').append(monshift);
        });
    }
}

// Load the shifts the member is registered to
function loadShiftPartner(partner_id) {
    $.getJSON('/shifts/get_list_shift_partner/' + partner_id, function(donnees) {
        // Init the partner's shifts list
        listeShiftPartner = [];
        donnees.forEach(function f(shift) {
            var dateStart = new Date(shift.date_begin);

            if (dateStart.getHours() < 22) {
                listeShiftPartner.push(shift);
            }
        });

        $('#shift_msg').remove();
        $('#partnerData').append('<div id="shift_msg"></div>');
        if (dataPartner.shift_type == "ftop" || listeShiftPartner.length > 0) {
        // ftop, no shift planned
            if (listeShiftPartner.length == 0) {
                var date = new Date(dataPartner.next_regular_shift_date);
                // ftop looses 1 point if points >=0, looses 2 otherwise
                var lost_points = "un point";

                if (dataPartner.final_ftop_point < 0) {
                    lost_points = "deux points";
                }

                var msg = "Je m'inscris à un service, en cliquant sur un des services du calendrier ci-dessous.<br/>";
                /*** TODO : add message structure to html #templates
          msg += "Si je ne fais pas de service avant le " + date.toLocaleDateString("fr-fr") + ", mon compteur perdra " + lost_points + ".  <i class=\"fas fa-info-circle\" title=\"Je clique pour avoir plus de détails.\"></i><div class=\"infocircle\"> <div class=\"close\" onclick=\"closeInfo(this)\"><i class=\"far fa-times-circle\"></i></div>Mon compteur sera diminué de 1 point le "+date.toLocaleDateString("fr-fr")+" si mon solde est supérieur ou égal à 0, sinon de 2 points, comme tous <strong>les jeudis de semaine A</strong> pour tou.te.s les volant.e.s.</div>"
          **/

                $('#shift_msg').append('<span id="new_shift_msg" class="highlight"><br />'+msg+'</span>');
            } else {
                $('#new_shift_msg').remove();

                // Set DOM for partner's shifts and shift message for ftops
                iniListShift(listeShiftPartner, true);
                if (dataPartner.shift_type == "ftop") {
                    $('#shift_msg').append("<br /><strong>Je peux choisir d'autres services pour les mois à venir ou échanger un de ceux de la liste.</strong>");
                }
            }
        }
    });
}

// Proceed to shift exchange or registration
function changeShift(idOldRegister, idNewShift) {
    if (is_time_to('change_shift')) {
        openModal(); // loading on

        tData = 'idNewShift=' + idNewShift +'&idPartner=' + dataPartner.partner_id + '&shift_type=' + dataPartner.shift_type + '&verif_token=' + dataPartner.verif_token;
        if (idOldRegister == "") {
            tUrl = '/shifts/add_shift';
        } else {
            register = listeShiftPartner.find(function(shift) {
                return shift.id === Number(idOldRegister);
            });
            tUrl = '/shifts/change_shift';
            tData = tData + '&idOldShift='+ register.shift_id[0] +'&idRegister=' + idOldRegister;
        }

        $.ajaxSetup({headers: {"X-CSRFToken": getCookie('csrftoken')}});
        $.ajax({
            type: 'POST',
            url: tUrl,
            dataType:"json",
            data: tData,
            timeout: 3000,
            complete: function () {
                $("#box_load").fadeOut();
            },
            success: function(data) {
                if (data.result) {
                    closeModal();
                    setTimeout( // Due to chrome effect
                        function() {
                            parent.window.postMessage('scrollToTop', '*');
                            msg = "Parfait! ";
                            if (idOldRegister == "") {
                                msg += "Le service choisi a été ajouté.";
                            } else {
                                msg += "Le service a été échangé.";
                            }
                            alert(msg);
                            loadShiftPartner(dataPartner.partner_id);
                            $('#dp').fullCalendar('refetchEvents');
                        }
                        , 500
                    );
                }
            },
            error: function(error) {
                closeModal();

                if (error.status === 400) {
                    alert(`Désolé ! Le service que vous souhaitez échanger démarre dans moins de 24h. Il n'est plus possible de l'échanger.`);

                } else {
                    alert('Une erreur est survenue. Il est néanmoins possible que la requête ait abouti, veuillez patienter quelques secondes puis vérifier vos services enregistrés.');
                }
                // Refectch shifts anyway:
                //  in case an error rises but the registration/exchange was still succesful
                setTimeout( // Due to chrome effect
                    function() {
                        loadShiftPartner(dataPartner.partner_id);
                        $('#dp').fullCalendar('refetchEvents');
                    }
                    , 500
                );
            }
        });
    }
}

// Check if the member can proceed to a service exchange
function canMakeExchange() {
    var answer = false;
    // Set the partner's limit date (after which he'll loose a point)

    if (dataPartner.dateProlonge != "False" || dataPartner.final_standard_point < 0 || dataPartner.shift_type == "ftop") {
        var dateProlonge = new Date(dataPartner.dateProlonge);
        var dateNextRegularShift = new Date(dataPartner.next_regular_shift_date);

        limitDate = dateNextRegularShift;

        // For ABCD : the limit date is end of alert
        var dateEndAlert = new Date(dataPartner.date_alert_stop);

        if (dataPartner.shift_type == "ftop" && limitDate < dateEndAlert) {
            limitDate = dateEndAlert;
        }

        // For partner in delay : limit date is end of delay
        if (dateProlonge - dateNextRegularShift < 0 || dataPartner.cooperative_state == 'delay') {
            limitDate = dateProlonge;
        }
    }

    let shifts_before_limit = 0;
    // If has shifts

    if (listeShiftPartner.length > 0) {
    // Calculate needed data
        non_regular_shifts = [];
        listeShiftPartner.forEach(function(s) {
            if (limitDate) {
                var s_date_begin = new Date(s.date_begin);

                if (s_date_begin - limitDate <= 0) {
                    shifts_before_limit += 1; // any shift before limit date
                }
                try {
                    if (s.shift_id[1].indexOf(dataPartner.regular_shift_name) == -1 && s_date_begin - limitDate <= 0) {
                        non_regular_shifts.push(s.date_begin); // non regular shifts before limit date
                    }
                } catch (e) {
                    //nothnig special to do
                }
            }
        });

        // Allow exchange if points >= 0 or he already has enough services booked before the limit date
        var partner_points = dataPartner.shift_type == "ftop" ? dataPartner.final_ftop_point : dataPartner.final_standard_point;

        if (partner_points >= 0 || shifts_before_limit >= 1) {
            answer = true;
        }

        // If member in alert, allow service exchange if he selected enough 'catch-ups'
        if (dataPartner.cooperative_state == "alert" || dataPartner.cooperative_state == "delay") {
            answer = (shifts_before_limit >= 1) && (non_regular_shifts.length >= Math.abs(partner_points));
        }

        // ftop can always exchange service
        if (dataPartner.shift_type == "ftop") {
            answer = true;
        }
    }

    return answer;
}

/*
Génère le message à afficher lorsque le coop doit faire un rattrapage.
  L'affiche si besoin.
  Pour les volants, chaque service compte comme un rattrapage.
*/
function addMakeUpMsg() {
    var partner_points = dataPartner.shift_type == "ftop" ? dataPartner.final_ftop_point : dataPartner.final_standard_point;
    let shifts_before_limit = 0;

    // Calcul du nombre de rattrapages à faire
    if (partner_points < 0) {
        let s_date_begin = null;

        // Calcul du nombre de rattrapages déjà prévus avant la date limite
        non_regular_shifts.forEach(function(s) {
            s_date_begin = new Date(s);
            if (s_date_begin > new Date() && s_date_begin - limitDate <= 0) {
                shifts_before_limit += 1;
            }
        });
        make_up_nb = parseInt(partner_points) + shifts_before_limit;
        // Besoin de choisir un rattrapage : afficher message rattrapage
        if (make_up_nb < 0) {
            make_up_nb = Math.abs(make_up_nb);
            var msg = "";

            var mun_letters = "un";

            if (make_up_nb == 2) {
                mun_letters = "deux";
            } else if (make_up_nb == 3) {
                mun_letters = "trois";
            } else if (make_up_nb == 4) {
                mun_letters = "quatre";
            } else if (make_up_nb == 5) {
                mun_letters = "cinq";
            }

            msg = "Je dois ";
            if (non_regular_shifts > 0) {
                msg += "encore";
            }
            msg += " m'inscrire à " + mun_letters + " service";
            if (make_up_nb > 1) {
                msg += "s de rattrapage en les sélectionant ";
            } else {
                msg +=" de rattrapage en en sélectionant un ";
            }
            msg +=" dans le calendrier ci-dessous.";

            if (make_up_nb > 1) {
                msg += "<br/>Ces services doivent être fait ";
            } else {
                msg += "<br/>Ce service doit être fait ";
            }

            // Si le membre est un volant
            if (dataPartner.shift_type == "ftop") {
                msg = "Je dois faire " + make_up_nb + " service";
                if (make_up_nb > 1) msg += "s";
                if (non_regular_shifts.length > 0) msg += " en plus";
            }

            msg += " avant le " + limitDate.toLocaleDateString("fr-fr", optDate) + ", faute de quoi je serai suspendu.e à cette date.";

            msg += "<br/>Je dois m'inscrire à tous mes services de rattrapage avant de pouvoir échanger mes services.";

            $('#partnerData').append("<p class=\"need_make_up_area\"><span class=\"need_make_up\"><strong>"+ msg + "</strong></span></p>");
            $('.need_make_up').show();
        } else {
            $('.need_make_up').hide();
        }
    } else {
        $('.need_make_up').hide();
    }
}

function manageCheckedBoxes() {
    let clicked = $(this);
    let checked = clicked.is(':checked');

    $('[name="shiftRadio"]').prop('checked', false);
    if (checked) clicked.prop('checked', checked);
}

/*
  Check if a partner can add a new shift.
  Those who can't are:
    - ftops, with points <0 and new service selected after limit date
    - ABCD up to date (or with enough catch-ups)
    - ABCD who choose catch-up after their limit date
*/
function canAddShift(date_new_shift) {
    var answer = false;

    // If partner is ftop (ftop = volant)
    if (dataPartner["shift_type"] == "ftop") {
    // If points >= 0 : can register to any shift
        if (dataPartner.final_ftop_point >= 0) {
            answer = true;
        } else {
            // If points < 0 : can only register to a shift before the limit date
            if (date_new_shift < limitDate) {
                answer = true;
            }
        }
    }
    // Rattrapages des ABCD
    else if (dataPartner["cooperative_state"] != "up_to_date") {
        // how many makeup have already been choosen ? (before end of alert)
        var dateEndAlert = null;

        if (dataPartner["dateProlonge"] == "False") {
            dateEndAlert = new Date(dataPartner["date_alert_stop"]);
        } else {
            dateEndAlert = new Date(dataPartner["dateProlonge"]);
        }

        var choosen_makeups = 0;

        $.each(listeShiftPartner, function(i, e) {
            if (new Date(e.date_begin) < dateEndAlert && e.shift_id[1].indexOf(dataPartner["regular_shift_name"]) < 0) {
                choosen_makeups++;
            }
        });

        // Si moins de rattrapages sélectionnés que de points à rattraper :
        //   dois faire un rattrapage, donc peut ajouter un service.
        if (choosen_makeups < Math.abs(dataPartner["final_standard_point"])) {
            // can only register to a shift before the limit date
            if (date_new_shift < limitDate) {
                answer = true;
            }
        }
    }

    return answer;
}

// Request a delay for the current member, starting at the end of his limit date
// TODO : shift_common
function request_delay() {
    openModal(); // Loading on

    var formated_limit_date = limitDate.getFullYear()+'-'+(limitDate.getMonth()+1)+'-'+limitDate.getDate();
    let delay_data = {
        idPartner: dataPartner.partner_id,
        verif_token: dataPartner.verif_token,
        start_date: formated_limit_date // date when the 28 days delay begins
    };

    // If not already in delay
    if (dataPartner.cooperative_state != 'delay') {
        let today = new Date();
        var extension_beginning = today.getFullYear()+'-'+(today.getMonth()+1)+'-'+today.getDate();

        // set today as the actual starting date for the object delay
        // so odoo take account of the delay
        delay_data['extension_beginning'] = extension_beginning;
    }

    $.ajaxSetup({headers: {"X-CSRFToken": getCookie('csrftoken')}});
    $.ajax({
        type: 'POST',
        url: '/shifts/request_delay',
        dataType: 'json',
        timeout: 3000,
        data: delay_data,
        success: function(doc) {
            closeModal();
            alert("L'extension a bien été accordée ! Cette page va se recharger...");
            setTimeout( // Due to chrome effect
                function() {
                    document.location.reload();
                }
                , 500
            );
        },
        error: function() {
            alert('Impossible de créer l\'extension. Je dois passer au Bureau des membres pour régler le problème.');
        }
    });
}


$(document).ready(function() {
    // Retrieve and display partner's shifs
    loadShiftPartner(dataPartner.partner_id);

    // Display information depending on partner's type and state
    if (dataPartner.shift_type == "ftop") {
        $('div.intro div h2').text("Bienvenue dans le système de choix et d'échange de services");
        $('.additionnal_intro_data').text(' ou en choisir un nouveau');

        var partnerData = "Je suis en statut <span class=\"status\">" + listStates[dataPartner.cooperative_state]+ "</span>.<br>";
        /** TODO : Change code to use a parameter to know if following assertion has to be shown or not
    partnerData += "Je suis volant.e et j'ai <strong>"+ dataPartner.final_ftop_point +" point";
    if(Math.abs(dataPartner.final_ftop_point) > 1) {
      partnerData += "s";
    }
    partnerData += "</strong>. "
    **/

        if (typeof extra_info !== "undefined" && extra_info.length > 0) {
            partnerData += '<br/>' + extra_info;
        }
        $('#partnerData').html(partnerData);
    } else {
        $('.additionnal_intro_data').text(' ou choisir un rattrapage');
        var msg = "Je suis inscrit.e sur le créneau du " + get_litteral_shift_template_name(dataPartner.regular_shift_name) + '.';

        if (dataPartner.final_standard_point < 0) {
            msg += " J'ai " + dataPartner.final_standard_point+" point";
            if (dataPartner.final_standard_point < -1) {
                msg += "s";
            }
            msg += ".";
        }
        $('#partnerData').html(msg);
        if (dataPartner.cooperative_state == "up_to_date") {
            $('#partnerData').append("<br> Je suis à jour.");
        } else {
            $('#partnerData').append("<br> Je suis en statut <span class=\"status\">"+ listStates[dataPartner.cooperative_state] +"</span>.<br />");
        }
        if (typeof extra_info !== "undefined" && extra_info.length > 0) {
            $('#partnerData').append("<br/>" + extra_info);
        }
    }

    if (dataPartner.is_leave == "True") {
        var dateFinConge = new Date(dataPartner.leave_stop_date);
        var dateDebutConge = new Date(dataPartner.leave_start_date);

        $('#partnerData').append("<br/> En congé du " + dateDebutConge.toLocaleDateString("fr-fr", optDate) + " au " + dateFinConge.toLocaleDateString("fr-fr", optDate) + '<br/>');
    }

    // Listeners on click
    $(document).on("click", ".fa-info-circle", function() {
        var clicked = $(this);

        clicked.parent().find('>.infocircle')
            .toggle();
    });
    $(document).on("click", '[name="shiftRadio"]', manageCheckedBoxes);

    // Set calendar

    dp = $('#dp').fullCalendar({
        header: {
            left: 'prev,next today',
            center: 'title',
            right: 'month,agendaWeek,agendaDay,listWeek'
        },
        timeFormat: 'HH:mm',
        locale: "fr",
        navLinks: true, // can click day/week names to navigate views
        eventLimit: showMoreLinks, // allow "more" link when too many events showMoreLinks defines in view HTML
        height: 900,
        minTime: "06:00:00",
        maxTime: "22:00:00",
        hiddenDays: daysToHide,
        initialView: calInitialView,
        weekNumbers: true,
        events: function(start, end, timezone, callback) {
            // Load possible shifts
            $.ajax({
                url: '/shifts/get_list_shift_calendar/' + dataPartner.partner_id,
                dataType: 'json',
                data: {
                    start: start.format('YYYY-MM-DD'),
                    end: end.format('YYYY-MM-DD')
                },
                success: function(doc) {
                    loaded_events = doc;
                    // Show service exchange panel if allowed
                    can_make_exchange = canMakeExchange();
                    if (can_make_exchange) {
                        $('#exchange_instructions').show();
                    }

                    // Show make-up instructions if needed
                    $('.need_make_up').remove();
                    addMakeUpMsg();

                    callback(loaded_events);
                }
            });
        },
        eventClick: function(event) {
            // When a service is clicked
            if (event.changed) {
                var dateShiftNew = new Date(event.start);

                can_make_exchange = canMakeExchange();
                can_add_shift = canAddShift(dateShiftNew);

                if (dataPartner.is_leave == "True" && (dateShiftNew < dateFinConge && dateShiftNew > dateDebutConge)) {
                    alert("Je suis en congé à cette date ... ");
                } else {
                    var idShiftOld = Number($('input[name=shiftRadio]:checked').val() || "");
                    var msg = '';

                    // si un service a été sélectionné --> Echange (pour tout le monde)
                    if (idShiftOld != "" && can_make_exchange) {
                        var resOldShift = listeShiftPartner.find(function(shift) {
                            return shift.id === idShiftOld;
                        });
                        var dateShiftOld = new Date(resOldShift.date_begin);

                        msg = '<div>Je suis sur le point d\'échanger le service du : </div>';
                        msg += '<div>' + dateShiftOld.toLocaleDateString("fr-fr", optDate) + ' à ' + dateShiftOld.toLocaleTimeString("fr-fr") +'</div>';
                        msg += '<div>par celui de : </div>';
                        msg += '<div>'+ dateShiftNew.toLocaleDateString("fr-fr", optDate) + ' à ' + dateShiftNew.toLocaleTimeString("fr-fr") + '</div>';
                    } else {
                        // Pas de service selectionné --> Ajout d'un service

                        // For partners who can't add a shift as it is
                        if (!can_add_shift) {
                            // Partners who could ask for a delay
                            if (dataPartner.shift_type == "ftop" || dateShiftNew > limitDate) {
                                // Member can ask for 6 delays, which is 24 weeks after entering alert status
                                // 'date_alert_stop' field is begining of alert + 4 weeks
                                let date_end_alert = new Date(dataPartner.date_alert_stop);

                                date_end_alert.setDate(date_end_alert.getDate()+20*7);

                                // If member can ask for delay
                                if (new Date() < date_end_alert) {
                                    openModal(
                                        "Pour pouvoir sélectionner un service à partir du <strong>" + limitDate.toLocaleDateString("fr-fr", optDate) + "</strong> je dois demander une extension.<br/>"
                            + "Je devrais re-sélectionner ce service dans l'agenda une fois l'extension accordée.",
                                        request_delay,
                                        "Demander une extension"
                                    );
                                } else {
                                    // can't ask for delays anymore
                                    openModal(
                                        "Je dois sélectionner un service <strong>avant le " + limitDate.toLocaleDateString("fr-fr", optDate) + "</strong>",
                                        closeModal, "J'ai compris"
                                    );
                                }
                            } else { // ABCD up-to-date
                                openModal(
                                    "Je dois sélectionner un service à échanger.",
                                    closeModal, "J'ai compris"
                                );
                            }
                            // Can add shift
                        } else {
                            msg = "<div>Je suis sur le point de m'inscrire au service du : </div>";
                            msg += '<div>'+ dateShiftNew.toLocaleDateString("fr-fr", optDate) + ' à ' + dateShiftNew.toLocaleTimeString("fr-fr") +'</div>';
                        }
                    }
                    if (msg != '') {
                        openModal(
                            msg,
                            function() {
                                var bl = $('#box_load');

                                bl.fadeIn(50);
                                bl.css('top', (lastY - 300) + 'px');
                                changeShift(idShiftOld, event.id);
                            }, 'Valider'
                        );
                    }
                }
            }
        }
    });

});

$(document).mousedown(function(e) {
    lastY = e.clientY;
});