// requires jquery 1.7+

// JS s'execute: Retire l'avertissement 'Javascript est requis' (de fait, on sait que JS est actif...)
document.body.classList.remove("nojs");

//### Helpers handlebars personnalisés
Handlebars.registerHelper('lower', function (options) {
    return options.fn(this).toLowerCase();
});

Handlebars.registerHelper('repuri', function (find, replace, options) {
    return encodeURI(options.fn(this).replace(find, replace).toString());
});

Handlebars.registerHelper('todate', function (options) {
    var d = options.fn(this);
    var dt = new Date(Number.parseInt(d) * 1);
    return dt.toLocaleString();
});

Handlebars.registerHelper('timestamp', function (options) {
    return Number.parseInt(options.fn(this));
});

Handlebars.registerHelper('if_eq', function (a, opts) {
    var b = localStorage.hasOwnProperty("contact") ? localStorage.getItem("contact") : "";
    if (a === b) // Or === depending on your needs
        return opts.fn(this);
    else
        return opts.inverse(this);
});


//### Initialisation

var db_version = "3"

// Installe le service worker
if ('serviceWorker' in navigator) {
    console.log("[ServiceWorker] Installe");
    navigator.serviceWorker.register('../sw.js');
}

var sectionId;
var section;

var load = function () {
    // Vide la section main
    $("#main").empty();

    // Page en cours
    sectionId = (window.location.hash.slice(1).length > 0 ? window.location.hash.slice(1) : "index");
    section = $("body").find('#' + sectionId);

    // compile la section avec handlebars
    if ($(section).attr("model")) {
        var model = $(section).attr("model");

        var template = Handlebars.compile(section.html());

        // Charge la base de données, et le stockage courant
        var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
        var request = indexedDB.open("MobiParc", db_version);
        var db;
        var txs;
        var store;

        // Cree les stockages necessaires si ceux ci sont manquants
        request.onupgradeneeded = function () {
            var db = request.result;
            db.createObjectStore(model, { keyPath: "tstamp" });
            console.log("[DB] Cree '" + model + "'");
        };

        request.onsuccess = function () {
            db = request.result;
            txs = db.transaction(model, "readonly");
            store = txs.objectStore(model);
            store.getAll().onsuccess = function (event) {
                var data = { data: event.target.result };
                $("#main").html(template(data));
            };
        };

        request.onerror = function () {
            console.log("Error while loading the db '" + model + "'");
            $("#main").html(template({}));
            return;
        };

        // Intercepte la soumision de formulaires
        $("#main").on("submit", ".data-form", function (event) {
            console.log("handle submit");

            var form = $("#main").find(".data-form")[0];

            // Stop the form from submitting since we’re handling that with AJAX.
            event.preventDefault();

            // Call our function to get the form data.
            var data = formToJSON(form.elements);

            // Demo only: print the form data onscreen as a formatted JSON object.
            var dataContainer = document.getElementsByClassName('results-display')[0];

            // Use `JSON.stringify()` to make the output valid, human-readable JSON.
            dataContainer.textContent = JSON.stringify(data, null, "  ");

            if ($(form).hasClass("activite")) {
                data.tstamp = Date.now();
                data.user = localStorage.hasOwnProperty("params") ? JSON.parse(localStorage.getItem("params")).user : "(unknown)";

                txs = db.transaction(model, "readwrite");
                store = txs.objectStore(model);
                store.put(data);
                
                store.getAll().onsuccess = function (event) {
                    $("#main").empty();
                    var data = { data: event.target.result };
                    var template = Handlebars.compile(section.html());
                    $("#main").html(template(data));
                };
            }
        });

        // Gere le clic sur un bouton supprimer
        $("body").on("click", ".del", function (event) {
            var del = $(this);
            if (confirm("Supprimer la selection!") == true) {

                $(del).prop("disabled", true);

                $(".ui-selected").each(function () {
                    var elt = $(this);
                    var id = $(elt).data("id");
                    //var datatype = $(elt).data("type");

                    txs = db.transaction(model, "readwrite");
                    store = txs.objectStore(model);
                    store.delete(id).onsuccess = function (evt) {
                        $(elt).remove();
                    };
                });
            }
        });

    }
    else {
        $("#main").html($(section).html());
    }

}

load();

// Recharge dynamiquement le contenu HTML à chaque changement d'url
$(window).on('hashchange', function () {
    console.log("Trigger: hashchange");
    load();
});


//######### MAIN  ###############

// ### Interactions

// Affiche ou masque la sidebar
$('.bt-menu').on('click', 'svg', function () {
    $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
});
$(document).on('click', '.sidebar', function () {
    $(this).closest('nav').find('div:not(:first)').toggleClass('sidebar');
});

// Affiche ou masque le bouton de sync
if (navigator.onLine) {
    $(".data-sync").removeAttr("disabled");
}
else {
    if (!$(".data-sync").is(":disabled"))
    {
        $(".data-sync").attr("disabled")
    }
}

/* retour haut de page*/
window.onscroll = function (ev) {
    document.getElementById("cRetour").className = (window.pageYOffset > 100) ? "cVisible" : "cInvisible";
};

$('#cRetour').on('click', function () {
    $('html, body').animate({ scrollTop: 0 }, 200);
});

// Gere l'affichage des classes modales
$(".modal-open, .modal-background, .modal-close").click(function () {
    $(".modal-content,.modal-background").toggleClass("active");
    if ($(this).hasClass("modal-close")) location.reload();
});

// Rend selectionables les lignes des tables (.selectable)
$("#main").selectable({
    filter: ".selectable tr",
    stop: function () {
        $(".del").removeAttr("disabled");
    }
});

// ### Synchronisation des données

$(".data-sync").on("click", function () {

    var db = open.result;
    var txs = db.transaction("activite", "readonly");
    var stores = txs.objectStore("activite");
    console.log("post all : ");
    stores.openCursor().onsuccess = function (event) {
        //var data =  { data: event.target.result };
        var cursor = event.target.result;
        if (cursor) {
            //cursor.model = "anomaly";

            cursor.value.model = "activite";
            var id = cursor.value.tstamp;
            var posting = $.post("/api/mobiparc", { data: JSON.stringify(cursor.value) });

            // Put the results in a div
            posting.done(function (data) {
                if (data == 'ole') {

                    var tx = db.transaction("activite", "readwrite");
                    var store = tx.objectStore("activite");
                    store.delete(id).onsuccess = function (evt) {
                        $('.sync-result').append("Sync ok activite : " + id + "<br>");
                    };
                }
            });
            cursor.continue();
        }
        else {
            console.log("end activite");
        }

    };
})



//###### TOOLBOX  ######

function createGuid() {
    return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
        (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
    )
}

function getLocation() {
    try {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(showPosition);
        } else {
            console.log("Geolocation is not supported by this browser.");
            return 0;
        }
    }
    catch (e) {
        console.log("Geolocation: error");
    }
}

function showPosition(position) {
    $("input[name='coordinates']").val(position.coords.latitude + "," + position.coords.longitude);
    console.log(position.coords);
}


// ### Serialization

/**
 * Checks that an element has a non-empty `name` and `value` property.
 * @param  {Element} element  the element to check
 * @return {Bool}             true if the element is an input, false if not
 */
var isValidElement = function isValidElement(element) {
    return element.name && element.value;
};

/**
 * Checks if an element’s value can be saved (e.g. not an unselected checkbox).
 * @param  {Element} element  the element to check
 * @return {Boolean}          true if the value should be added, false if not
 */
var isValidValue = function isValidValue(element) {
    return !['checkbox', 'radio'].includes(element.type) || element.checked;
};

/**
 * Checks if an input is a checkbox, because checkboxes allow multiple values.
 * @param  {Element} element  the element to check
 * @return {Boolean}          true if the element is a checkbox, false if not
 */
var isCheckbox = function isCheckbox(element) {
    return element.type === 'checkbox';
};


//var isHidden = function isHidden(element) {
//    return element.type === 'hidden';
//};

/**
 * Checks if an input is a `select` with the `multiple` attribute.
 * @param  {Element} element  the element to check
 * @return {Boolean}          true if the element is a multiselect, false if not
 */
var isMultiSelect = function isMultiSelect(element) {
    return element.options && element.multiple;
};

/**
 * Retrieves the selected options from a multi-select as an array.
 * @param  {HTMLOptionsCollection} options  the options for the select
 * @return {Array}                          an array of selected option values
 */
var getSelectValues = function getSelectValues(options) {
    return [].reduce.call(options, function (values, option) {
        return option.selected ? values.concat(option.value) : values;
    }, []);
};

/**
 * A more verbose implementation of `formToJSON()` to explain how it works.
 *
 * NOTE: This function is unused, and is only here for the purpose of explaining how
 * reducing form elements works.
 *
 * @param  {HTMLFormControlsCollection} elements  the form elements
 * @return {Object}                               form data as an object literal
 */
var formToJSON_deconstructed = function formToJSON_deconstructed(elements) {

    // This is the function that is called on each element of the array.
    var reducerFunction = function reducerFunction(data, element) {

        // Add the current field to the object.
        data[element.name] = element.value;

        // For the demo only: show each step in the reducer’s progress.
        console.log(JSON.stringify(data));

        return data;
    };

    // This is used as the initial value of `data` in `reducerFunction()`.
    var reducerInitialValue = {};

    // To help visualize what happens, log the inital value, which we know is `{}`.
    console.log('Initial `data` value:', JSON.stringify(reducerInitialValue));

    // Now we reduce by `call`-ing `Array.prototype.reduce()` on `elements`.
    var formData = [].reduce.call(elements, reducerFunction, reducerInitialValue);

    // The result is then returned for use elsewhere.
    return formData;
};

/**
 * Retrieves input data from a form and returns it as a JSON object.
 * @param  {HTMLFormControlsCollection} elements  the form elements
 * @return {Object}                               form data as an object literal
 */
var formToJSON = function formToJSON(elements) {
    return [].reduce.call(elements, function (data, element) {

        // Make sure the element has the required properties and should be added.
        if (isValidElement(element) && isValidValue(element)) {

            /*
             * Some fields allow for more than one value, so we need to check if this
             * is one of those fields and, if so, store the values as an array.
             */
            if (isCheckbox(element)) {
                data[element.name] = (data[element.name] || []).concat(element.value);
            } else if (isMultiSelect(element)) {
                data[element.name] = getSelectValues(element);
            } else {
                data[element.name] = element.value;
            }
        }

        return data;
    }, {});
};