// DEFINE

var array_keys_chiffres = ['1','2','3','4','5','6','7','8','9','0'];
var array_keys_ponctuations = ['.','-','_','#','@'];
var array_keys_minuscules = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'];
var array_keys_majuscules = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];

function isDefined(val){
    return (val === undefined || val == null || val.length <= 0) ? false : true;
}

/* MODAL FORM UTIL */

function modalForm_initBtnView(btn, modal, clearFormFct, loadFormDatasFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        clearFormFct(modal);
        modal.attr("view_id", id);
        loadFormDatasFct(modal, id);
    });
}

function modalForm_initBtnAdd(btn, modal, clearFormFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        clearFormFct(modal);
        modal.modal('show');
    });
}

function modalForm_initBtnCopy(btn, modal, clearFormFct, loadFormDatasFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        clearFormFct(modal);
        loadFormDatasFct(modal,id, true);
    });
}

function modalForm_initBtnSaveAdd(btn, addType, modal, getModalFormDataFct, checkModalFormDataFct, saveURL) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        
        // GET & CHECK DATAS
        var datas = getModalFormDataFct(modal);
        console.log("modalForm_btnSaveAdd", datas);
        if( !checkModalFormDataFct(datas) ) return;
        datas.action = 'add';
        
        // RUN REQUEST
        modalForm_runFormRequest( saveURL, datas, ("add "+addType) , modal, $(this) );
    });
}

function modalForm_initBtnEdit(btn, modal, clearFormFct, loadFormDatasFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        clearFormFct(modal);
        modal.attr("edit_id", id);
        loadFormDatasFct(modal,id);
    });
}

function modalForm_initBtnSaveEdit(btn, editType, modal, getModalFormDataFct, checkModalFormDataFct, saveURL) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        
        // GET MODAL EDIT ID
        var id = parseInt( modal.attr("edit_id") );
        if(!id>0) return;
        
        // GET & CHECK DATAS
        var datas = getModalFormDataFct(modal);
        console.log("modalForm_btnSaveEdit", datas);
        if( !checkModalFormDataFct(datas) ) return;
        datas.action = 'edit';
        datas.ref = id;
        
        // RUN REQUEST
        modalForm_runFormRequest( saveURL, datas, ("edit "+editType) , modal, $(this) );
    });
}

function modalForm_initBtnArchive(btn, modal, clearFormFct, loadFormDatasFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        clearFormFct(modal);
        modal.attr("archive_id", id);
        loadFormDatasFct($(this),id);
    });
}

function modalForm_initBtnSaveArchive(btn, archiveType, modal, saveURL) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        
        // GET MODAL DELETE ID
        var id = parseInt( modal.attr("archive_id") );
        if(!id>0) return;
        
        // GET DATAS
        var datas = {
            'action' : 'archive',
            'ref' : id
        };
        console.log("ARCHIVE", id, datas );
        
        // RUN REQUEST
        modalForm_runFormRequest( saveURL, datas, ("archive "+archiveType) , modal, $(this) );
    });
}

function modalForm_initBtnUnarchive(btn, archiveType, modal, saveURL) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        
        var datas = {
            'action' : 'unarchive',
            'ref' : id
        };
        console.log("UNARCHIVE", id, datas );
        
        // RUN REQUEST
        $.post( saveURL, datas, function( result ) {
            if(parseInt(result)>0) document.location.reload();
            else {
                console.error(result); alert(result);
            }
        }).fail(function(xhr) {
            var errMsg = "SERVER ERROR (unarchive "+archiveType+")";
            if( xhr['responseText']!="" ) errMsg += " : " + xhr['responseText'];
            console.error(errMsg); alert(errMsg);
        });
    });
}


function modalForm_initBtnDelete(btn, modal, clearFormFct, loadFormDatasFct) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        id = parseInt($(this).attr('ref'));
        if(!id>0) return;
        clearFormFct(modal);
        modal.attr("delete_id", id);
        loadFormDatasFct($(this),id);
    });
}

function modalForm_initBtnSaveDelete(btn, deleteType, modal, getModalFormDataFct, checkModalFormDataFct, saveURL) {
    btn.unbind('click').click( function(e) {
        e.preventDefault(); $(this).blur();
        
        // GET MODAL DELETE ID
        var id = parseInt( modal.attr("delete_id") );
        if(!id>0) return;
        
        // GET & CHECK DATAS
        var datas = {};
        if(typeof getModalFormDataFct === 'function') datas = getModalFormDataFct(modal);
        console.log("DELETE", id, datas );
        if(typeof checkModalFormDataFct === 'function') { if( !checkModalFormDataFct(datas) ) return; }
        datas.action = 'delete';
        datas.ref = id;
        
        // RUN REQUEST
        modalForm_runFormRequest( saveURL, datas, ("delete "+deleteType) , modal, $(this) );
    });
}

function modalForm_runFormRequest(url, datas, srvErrorAction, modal, btnRun) {
    modalForm_runFormRequest_lockModal(modal, btnRun);
    $.post( url, datas, function( result ) {
        if(parseInt(result)>0) {
            if(modal && modal.length>0) {
                modal.modal('hide');
                setTimeout(function() { document.location.reload(); },200);
            }
            else document.location.reload();
        }
        else {
            console.error(result); alert(result);
            modalForm_runFormRequest_unlockModal(modal, btnRun);
        }
    }).fail(function(xhr) {
        var errMsg = "SERVER ERROR";
        if( isDefined( srvErrorAction ) ) errMsg += " ("+srvErrorAction+")";
        if( xhr['responseText']!="" ) errMsg += " : " + xhr['responseText'];
        console.error(errMsg); alert(errMsg);
        modalForm_runFormRequest_unlockModal(modal, btnRun);
    });
}

function modalForm_runFormRequest_lockModal(modal, btnRun) {
    if( isDefined( modal ) && modal.find("div.modaLoader").length>0) modal.find("div.modaLoader").addClass("show");
    if( isDefined( btnRun ) ) btnRun.prop("disabled", true);
}

function modalForm_runFormRequest_unlockModal(modal, btnRun) {
    if( isDefined( modal ) && modal.find("div.modaLoader").length>0) modal.find("div.modaLoader").removeClass("show");
    if( isDefined( btnRun ) ) btnRun.prop("disabled", false);
}

function modalForm_initTabs(modal) {
    // TABS
    modal.find("a.formTabBtn").click(function(e) {
        e.preventDefault();
        
        // BTN
        if(!$(this).parent().hasClass("active")) {
            modal.find("ul.formTabsBtns > li").removeClass('active');
            $(this).parent().addClass("active");
        }
        
        // TAB
        var tab = modal.find("div.tab."+$(this).attr("tab"));
        if(tab.length>0) {
            if(tab.hasClass("active")) return;
            
            modal.find("div.formTabs > div.tab").removeClass("active");
            tab.addClass("active");
        }
    });
    
    // RESIZE TABS
    var resizeFct = function resizeFormClient(modal) {
        var wh = window.innerHeight;
        modal.find("div.formTabs div.tab").css("max-height", (wh-180)+"px");
    }
    resizeFct(modal);
    $( window ).on( "resize", function() { resizeFct(modal) });
}

function modalForm_resetTabs(modal) {
    modal.find("ul.formTabsBtns > li").removeClass('active hide');
    modal.find("ul.formTabsBtns > li:first-child").addClass('active');
    modal.find("div.formTabs > div.tab").removeClass("active");
    modal.find("div.formTabs > div.tab:first-child").addClass("active");
}

/* INLINE SELECT MANAGER */

function inlineSelectManager_init(
    modal,
    modal_form_name,
    grp,
    value_name,
    url,
    ref_attr,
    add_action, 
    edit_action, 
    delete_action,
    refresh_list_action,
    selectClbkFct,
    addClbkFct,
    editClbkFct,
    cancelClbkFct,
    getDatasFct,
    checkDatasFct,
    saveClbkFct
) {
    grp.attr("modal_form_name", modal_form_name)
       .attr("value_name", value_name)
       .attr("ref_attr", ref_attr)
       .attr("add_action", add_action)
       .attr("edit_action", edit_action)
       .attr("delete_action", delete_action)
       .attr("refresh_list_action", refresh_list_action);
    
    // SELECT CHANGE => SWITCH ACTION
    grp.find("select").change(function(e) {
        $(this).blur();
        // EXISTING
        if(parseInt($(this).val())>0) {
            inlineSelectManager_switchBtnAction(grp, "delete");
            inlineSelectManager_switchBtnSecondAction(grp, "edit");
        }
        // CHOISIR...
        else {
            inlineSelectManager_switchBtnAction(grp, "add");
            inlineSelectManager_switchBtnSecondAction(grp, "hide");
        }
        
        if(typeof selectClbkFct === 'function') selectClbkFct(modal, grp, $(this));
    });
    
    // BTN ACTION
    grp.find("button.btnAction").click(function(e) {
        e.preventDefault(); $(this).blur();
        // ADD / SAVE NEW
        if($(this).hasClass("add") || $(this).hasClass("save_new")) {
            inlineSelectManager_addInputName(grp, "add");
            inlineSelectManager_switchBtnAction(grp, "save");
            inlineSelectManager_switchBtnSecondAction(grp, "cancel");
            if(typeof addClbkFct === 'function') addClbkFct(modal, grp);
        }
        // SAVE
        else if($(this).hasClass("save")) inlineSelectManager_save(modal, grp, url, getDatasFct, checkDatasFct, saveClbkFct);
        // DELETE
        else if($(this).hasClass("delete")) inlineSelectManager_delete(modal, grp, url);
    });
    
    // BTN SECOND ACTION
    grp.find("button.btnSecondAction").click(function(e) {
        e.preventDefault(); $(this).blur();
        // EDIT
        if($(this).hasClass("edit")) {
            inlineSelectManager_addInputName(grp, "edit");
            inlineSelectManager_switchBtnAction(grp, "save");
            inlineSelectManager_switchBtnSecondAction(grp, "cancel");
            if(typeof editClbkFct === 'function') editClbkFct(modal, grp);
        }
        // CANCEL
        else if($(this).hasClass("cancel")) {
            inlineSelectManager_removeInputName(grp);
            // EDIT
            if(parseInt(grp.find("select").val())>0) {
                inlineSelectManager_switchBtnAction(grp, "delete");
                inlineSelectManager_switchBtnSecondAction(grp, "edit");
            }
            // ADD
            else {
                inlineSelectManager_switchBtnAction(grp, "add");
                inlineSelectManager_switchBtnSecondAction(grp, "hide");
            }
            
            if(typeof cancelClbkFct === 'function') cancelClbkFct(modal, grp);
        }        
    });
}

function inlineSelectManager_setValue(grp, val) {
    if(isDefined(val) && parseInt(val) > 0) {
        grp.find("select").val(val);
        inlineSelectManager_switchBtnAction(grp, "delete");
        inlineSelectManager_switchBtnSecondAction(grp, "edit");
    }
    else {
        grp.find("select").val("0");
        inlineSelectManager_switchBtnAction(grp, "add");
        inlineSelectManager_switchBtnSecondAction(grp, "hide");
    }
}

function inlineSelectManager_switchBtnAction(grp, action) {
    var btn = grp.find("button.btnAction");
    
    if(action == "add") {
        btn.removeClass("save save_new delete").addClass("add").removeClass("btn-danger btn-primary").addClass("btn-default")
           .find("i").removeClass("glyphicon-floppy-saved glyphicon-floppy-disk glyphicon-trash").addClass("glyphicon-plus");
    }
    else if(action == "save") {
        btn.removeClass("add save_new delete").addClass("save").removeClass("btn-danger btn-default").addClass("btn-primary")
           .find("i").removeClass("glyphicon-plus glyphicon-floppy-disk glyphicon-trash").addClass("glyphicon-floppy-saved");
    }
    else if(action == "save_new") {
        btn.removeClass("add save delete").addClass("save_new").removeClass("btn-danger btn-primary").addClass("btn-default")
           .find("i").removeClass("glyphicon-plus glyphicon-floppy-saved glyphicon-trash").addClass("glyphicon-floppy-disk");
    }
    else if(action == "delete") {
        btn.removeClass("add save_new save").addClass("delete").removeClass("btn-default btn-primary").addClass("btn-danger")
           .find("i").removeClass("glyphicon-plus glyphicon-floppy-saved glyphicon-floppy-disk").addClass("glyphicon-trash");
    }
}

function inlineSelectManager_switchBtnSecondAction(grp, action) {
    var btn = grp.find("button.btnSecondAction");
    
    if(action == "cancel") {
        btn.removeClass("edit").addClass("cancel").removeClass("btn-default").addClass("btn-danger")
           .find("i").removeClass("glyphicon-edit").addClass("glyphicon-floppy-remove");
        btn.parent().removeClass("hide");
    }
    else if(action == "edit") {
        btn.removeClass("cancel").addClass("edit").removeClass("btn-danger").addClass("btn-default")
           .find("i").removeClass("glyphicon-floppy-remove").addClass("glyphicon-edit");
        btn.parent().removeClass("hide");
    }
    else if(action == "hide") {
        btn.parent().addClass("hide");
    }
}

function inlineSelectManager_addInputName(grp, action) {
    var select = grp.find("select");
    select.addClass("hide");
    
    var ipt = $('<input type="text" class="form-control" name="name" placeholder="nom">').attr("action", action);
    ipt.insertBefore(select);
    
    if(action=="edit") {
        ipt.attr("ref", select.val());
        ipt.val( select.find("option:selected").html() );
    }
    else ipt.attr("ref", "new");
    ipt.focus();
    
    ipt.keypress(function(e) {
        if(e.keyCode==13) {
            e.preventDefault();
            $(this).parent().find("button.btnAction").click();
        }
    });
}

function inlineSelectManager_removeInputName(grp) {
    var ipt = grp.find("input[name=name]");
    if(ipt.length>0) ipt.remove();
    grp.find("select").removeClass("hide");
}

function inlineSelectManager_save(modal, grp, url, getDatasFct, checkDatasFct, saveClbkFct) {
    // GET DATAS
    var datas = (typeof getDatasFct === 'function') ? getDatasFct(modal, grp) : inlineSelectManager_getDatas(grp);
    
    // CHECK DATAS
    if(typeof checkDatasFct === 'function') { if( !checkDatasFct(datas) ) return; }
    else { if( !inlineSelectManager_checkDatas(datas) ) return; }
    
    var ref = grp.find("input[name=name]").attr("ref");
    
    // ADD
    if(ref == "new") datas.action = grp.attr("add_action");
    // EDIT
    else if(parseInt(ref)>0) {
        ref = parseInt(ref);
        datas.action = grp.attr("edit_action");
        datas[grp.attr("ref_attr")] = ref;
    }
    
    // LOCK
    modal.find("div.modaLoader").addClass("show");
    modal.find("button.btnAction").prop("disabled", true);
    
    $.post( url, datas, function( result ) {
        if(parseInt(result)>0) {
            inlineSelectManager_switchBtnAction(grp, "delete");
            inlineSelectManager_switchBtnSecondAction(grp, "edit");
            inlineSelectManager_removeInputName(grp);

            if(ref == "new") ref = parseInt(result);
            
            if(typeof saveClbkFct === 'function') saveClbkFct(modal, grp, ref);

            // REFRESH LIST
            $.post( url, { action: grp.attr("refresh_list_action") }, function( result ) {
                grp.find("select").html(result).val(ref);
            }).fail(function() { 
                alert("ERREUR SERVEUR ! (modal form "+grp.attr("modal_form_name")+" - add/edit "+grp.find("select").attr("name")+" - refresh list after)"); 
            });
        }
        else { console.error(result); alert(result); }
    }).fail(function() { 
        alert("ERREUR SERVEUR ! (modal form "+grp.attr("modal_form_name")+" - add/edit "+grp.find("select").attr("name")+")"); 
    }).always(function() {
        // UNLOCK
        modal.find("div.modaLoader").removeClass("show");
        modal.find("button.btnAction").prop("disabled", false);
    });
}

function inlineSelectManager_delete(modal, grp, url) {
    var ref = parseInt(grp.find("select").val());
    var nom = grp.find("select option:selected").html();
    
    if(confirm('Etês vous sûr de vouloir supprimer '+grp.attr('value_name')+' "'+nom+'" ?')) {
        // LOCK
        modal.find("div.modaLoader").addClass("show");
        modal.find("button.btnGroupeAction").prop("disabled", false);
        
        var datas = { action : grp.attr("delete_action") };
        datas[grp.attr("ref_attr")] = ref;
        
        $.post( url, datas, function( result ) {
            if(parseInt(result)>0) {
                // REFRESH LIST
                $.post( url, { action: grp.attr("refresh_list_action") }, function( result ) {
                    grp.find("select").html(result).val("0");
                }).fail(function() { 
                    alert("ERREUR SERVEUR ! (modal form "+grp.attr("modal_form_name")+" - delete "+grp.find("select").attr("name")+" - refresh list after)"); 
                });
            }
            else { console.error(result); alert(result); }
        }).fail(function() { 
        alert("ERREUR SERVEUR ! (modal form "+grp.attr("modal_form_name")+" - delete "+grp.find("select").attr("name")+")"); 
        }).always(function() {
            // UNLOCK
            modal.find("div.modaLoader").removeClass("show");
            modal.find("button.btnAction").prop("disabled", false);
        });
    }
}

function inlineSelectManager_getDatas(grp) {
    var datas = { 'nom' : grp.find("input[name=name]").val() };
    return datas;
}

function inlineSelectManager_checkDatas(datas) {
    if(datas.nom=="") {
        alert("Merci de renseigner un nom !");
        return false;
    }
    return true;
}

/* AUTOCOMPLETE INPUT */

function initAutocompleteInput(form, ipt, url, action, errContext, requestDataFct, selectFct, clearFct, blurFct) {
    ipt.autocomplete({
        html: true,
        delay: 200,
        source: function(requete, reponse) {
            datas = {
                'action' : action,
                'search' : ipt.val(),
                'nohist' : true
            };
            if(typeof requestDataFct === 'function') datas = requestDataFct(form, ipt, datas);
            $.post(url, datas, function(jsonTxt) {
                datas = JSON.parse(jsonTxt);
                reponse(datas);
            }).fail(function() { alert("ERREUR SERVEUR !"+( (isDefined(errContext)) ? " "+errContext : "" )); });
        },
        focus: function(event, ui) { event.preventDefault(); },
        select: function(event, ui) {
            event.preventDefault();
            if(typeof selectFct === 'function') selectFct(form, ipt, ui.item);
            else ipt.val( ui.item.value ).attr('ref', ui.item.ref).blur();
        }
    });
    ipt.keydown(function(e) {
        if(e.keyCode==13) { e.preventDefault(); $(this).blur(); }
        else if(parseInt($(this).attr('ref'))>0) {
            if(typeof clearFct === 'function') clearFct(form, $(this));
            else $(this).val("").removeAttr('ref');
        }
    });
    ipt.on("blur", function(e) {
        if(typeof blurFct === 'function') blurFct(form, $(this));
        else if(!parseInt($(this).attr('ref'))>0) $(this).val("").removeAttr('ref');
    });
}

/* LIST PROGRESS LOAD */

function initListProgressLoad(list, url, listName) {
    if(isDefined(list)) {
        var contentH = list.innerHeight();
        
        list.listProgressLoad_resize();
        $(window).resize( function() { list.listProgressLoad_resize(); } );

        list.scroll(function(e) {
            var rest = list.prop("scrollHeight") - list.innerHeight() - list.scrollTop();
            if(rest<300 && list.find("td.loader").length==0 && parseInt(list.attr('rest'))>0) {
                // APPEND LOADER
                var tr = $("<tr class='loader'><td class='loader' colspan='17'></td></tr>");
                list.append(tr);

                // LOAD
                $.post(url, { 'startListAt' : parseInt(list.attr('end')) }, function(jsonTxt) {
                    datas = JSON.parse(jsonTxt);

                    list.attr("start", datas.start);
                    list.attr("end", datas.end);
                    list.attr("rest", datas.rest);
                    list.append($(datas.list));

                    list.trigger( "loaded" );

                    tr.remove();
                }).fail(function(xhr) {
                    errMsg  = "SERVER ERROR ("+(( isDefined( listName ) && listName != "" ) ? listName : "list")+" - load items)";
                    if( xhr['responseText']!="" ) errMsg += " : " + xhr['responseText'];
                    console.error(errMsg); alert(errMsg);
                });
            }
        });
        
        // FORCE LOAD IF WINDOWS NOT FULL
        h = $(window).innerHeight() - list.position().top;
        if(parseInt(list.attr("rest"))>0 && contentH<h) list.trigger("scroll");
    }
}

function registerListProgressLoadCbkFct(list, clbFct) { if( isDefined(list) && (typeof clbFct === 'function')) list.on("loaded", clbFct); }

$.fn.listProgressLoad_resize = function() {
    var h = $(window).innerHeight() - $(this).position().top;
    $(this).removeAttr("style");
    if($(this).prop("scrollHeight") < h) $(this).parent().addClass("no-scroll");
    else $(this).parent().removeClass("no-scroll");
    $(this).css("height", h);
};

/* SEARCH */

$.fn.initSearchGroup = function() {
    $(this).find("input[search]").unbind('keypress').keypress( function(event) {
        if(event.keyCode==13) {
            $(this).blur();
            document.location = "?search="+$(this).val();
        }
    });
    $(this).find(".btnClearSearch").unbind('click').click( function(event) {
        event.preventDefault(); $(this).blur();
        document.location = "?clearSearch";
    });
}

$.fn.initFiltreSelect = function() {
    // LOAD VALUE
    $(this).each(function(n,e) {
        if(isDefined($(this).attr("load_value"))) $(this).val($(this).attr("load_value"));
    });
    
    // SELECT
    $(this).change(function(e) {
        if( !isDefined( $(this).attr("filtre_request") ) ) return;
        $(this).blur();
        document.location = "?"+$(this).attr("filtre_request")+"="+$(this).val();
    });
}

/* FONCTIONS */

function getUrlParameters() {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        params = [],
        i;
    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');
        params[sParameterName[0]] = (sParameterName[1] === undefined) ? true : decodeURIComponent(sParameterName[1]);
    }
    return params;
}

function getUrlParameter(sParam) {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        i;

    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');

        if (sParameterName[0] === sParam) {
            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
        }
    }
    return false;
}

function beep(duration, frequency, volume, type, callback) {
    var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
    var oscillator = audioCtx.createOscillator();
    var gainNode = audioCtx.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    
    if(volume) gainNode.gain.value = volume;
    if(frequency) oscillator.frequency.value = frequency;
    if(type) oscillator.type = type;
    if(callback) oscillator.onended = callback;
    
    oscillator.start(audioCtx.currentTime);
    oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
}

function number_format(number, decimals, dec_point, thousands_sep) {
  number = (number + '')
    .replace(/[^0-9+\-Ee.]/g, '');
  var n = !isFinite(+number) ? 0 : +number,
    prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
    sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep,
    dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
    s = '',
    toFixedFix = function(n, prec) {
      var k = Math.pow(10, prec);
      return '' + (Math.round(n * k) / k)
        .toFixed(prec);
    };
  // Fix for IE parseFloat(0.55).toFixed(0) = 0;
  s = (prec ? toFixedFix(n, prec) : '' + Math.round(n))
    .split('.');
  if (s[0].length > 3) {
    s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  }
  if ((s[1] || '')
    .length < prec) {
    s[1] = s[1] || '';
    s[1] += new Array(prec - s[1].length + 1)
      .join('0');
  }
  return s.join(dec);
}

function initFiltreInputNumber() {
    iptsInt = $(".inputIntNumber");
    iptsFloat = $(".inputFloatNumber");

    if(iptsInt.length>0) initIntInput(iptsInt);

    if(iptsFloat.length>0) initFloatInput(iptsFloat);
}

function initIntInput(elem) {
    elem.unbind('keypress').keypress( function(event) {
        keys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
        if(event.keyCode==13) $(this).blur();
        if(jQuery.inArray(event.keyCode,keys)==-1) event.preventDefault();
    });
}

function initIntInputWithLimits(elem, min, max) {
    elem.unbind('keypress').keypress( function(event) {
        keys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57];
        if(event.keyCode==13) {
            $(this).blur();
            if(parseInt($(this).val()>max)) $(this).val(max);
            else if(parseInt($(this).val()<min)) $(this).val(min);
        }
        if(jQuery.inArray(event.keyCode,keys)==-1) event.preventDefault();
    });
}

function initFloatInput(elem) {
    elem.unbind('keypress').unbind('keyup').keypress( function(event) {
        keys = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 46, 44];
        if(event.keyCode==13) $(this).blur();
        if(jQuery.inArray(event.keyCode,keys)==-1) event.preventDefault();
        if((event.keyCode==46 || event.keyCode==44) && $(this).val().indexOf('.')>0) event.preventDefault();   
    }).keyup( function(event) {
        if(event.keyCode==188 && $(this).val().indexOf('.')==-1) {
            var pos = $(this)[0].selectionStart;
            $(this).val( $(this).val().replace(",",".") );
            $(this)[0].setSelectionRange(pos,pos);
        }
    });
}

function initEdiTable(elem,beforeFct,callbacbFct) {
    elem.unbind('dblclick').dblclick( function(e) {
        var cell = $(this);
        
        if(cell.parent().parent().find('.ediTabling').length>0 || cell.hasClass('ediTabling') || cell.hasClass('disabled')) return;

        var origVal = cell.html();
        cell.attr('orig_val',origVal);
        cell.addClass('ediTabling');
        
        if(beforeFct) beforeFct(cell,e);

        ipt = $("<input class='ediTable' type='text'>");
        ipt.val(origVal);
        cell.html("").append(ipt);

        ipt.focus(function() {
           $(this).select();
        });

        ipt.blur( function(e) {
            val = $(this).val();
            if(cell.hasClass('int')) val = parseInt(val);
            if(cell.hasClass('float')) {
                dec_max = parseInt(cell.attr('float_dec'));
                dec_max = (!isNaN(dec_max) && dec_max>0) ? dec_max : 2;
                dec = 2;
                if(dec_max>=3) {
                    for(i = 3; i<=dec_max; i++) {
                        x = Math.pow(10, (i-1));
                        if(parseInt(((val*x) - parseInt(val*x))*10)>0) dec = i;
                    }
                }
                val = parseFloat(val).toFixed(dec);
            }
            
            $(this).remove();
            cell.removeClass('ediTabling').removeAttr('orig_val').html(val);
            
            clbFctReturn = false;
            if(callbacbFct) clbFctReturn = callbacbFct(cell,e);
            
            if(!clbFctReturn) {
                var nextFocus = false;
                cell.parent().find('.ediTable').each( function(n,e) {
                    if( $(this).attr('id') == cell.attr('id') ) nextFocus = new Array();
                    else if(nextFocus && nextFocus.length==0) nextFocus = $(this);
                });
                if(nextFocus && nextFocus.length>0) nextFocus.dblclick();
            }
        });
        
        ipt.keypress( function(event) {
            if(event.keyCode==13) $(this).blur();
        });
            
        if(cell.hasClass('int')) initIntInput(ipt);
        if(cell.hasClass('float')) initFloatInput(ipt);
        
        if(cell.hasClass('center')) ipt.addClass('center');
        if(cell.hasClass('align_right')) ipt.addClass('align_right');
        
        ipt.focus();
    });
}

function initUpperCaseInput(elem,beforeFct,callbacbFct) {
    elem.keyup( function(event) {
        if(beforeFct) beforeFct(elem,event);
        
        ignoreKeys = [8, 16, 46, 20, 37, 38, 39, 40];
        if(jQuery.inArray(event.keyCode,ignoreKeys)!=-1) return;
        
        pos = getCursorPosition($(this));
        $(this).val( $(this).val().toUpperCase() );
        setCursorPosition($(this),pos);
        
        if(callbacbFct) callbacbFct(elem,event);
    });
}

function initFirstUpperCaseInput(elem,beforeFct,callbacbFct) {
    elem.keyup( function(event) {
        if(beforeFct) beforeFct(elem,event);
        
        ignoreKeys = [8, 16, 46, 20, 37, 38, 39, 40];
        if(jQuery.inArray(event.keyCode,ignoreKeys)!=-1) return;
        
        pos = getCursorPosition($(this));
        $(this).val($(this).val().substr(0,1).toUpperCase() + $(this).val().substring(1));
        setCursorPosition($(this),pos);
        
        if(callbacbFct) callbacbFct(elem,event);
    });
}

function initTelInput(elem,feedback) {
    elem.intlTelInput({
        validationScript: "libs/intl-tel-input/build/js/isValidNumber.js",
        preferredCountries : ['fr'],
        nationalMode: false
    });
    if(feedback===true) {
        elem.blur(function() {
            if ($.trim($(this).val())) {
                if ($(this).intlTelInput("isValidNumber")) {
                    $(this).parent().parent().addClass('has-success');
                    $(this).parent().parent().find(".form-control-feedback").removeClass('glyphicon-warning-sign').addClass('glyphicon-ok').removeClass('hide');
                }
                else {
                    $(this).parent().parent().addClass('has-warning');
                    $(this).parent().parent().find(".form-control-feedback").addClass('glyphicon-warning-sign').removeClass('glyphicon-ok').removeClass('hide');
                }
            }
        }).keydown(function() {
            $(this).parent().parent().removeClass('has-success').removeClass('has-warning');
            $(this).parent().parent().find(".form-control-feedback").addClass('hide');
        });
    }
}

function initEmailInput(elem) {
    elem.blur( function(event) {
        checkEmail($(this));
    }).keydown(function() {
        $(this).parent().removeClass('has-success').removeClass('has-warning');
        $(this).parent().find(".form-control-feedback").addClass('hide');
    }).keyup(function() {
        $(this).val( $(this).val().toLowerCase() );
    });
}

function checkEmail(e) {
    if ($.trim(e.val())) {
        if (validateEmail(e.val())) {
            e.parent().addClass('has-success');
            e.parent().find(".form-control-feedback").removeClass('glyphicon-warning-sign').addClass('glyphicon-ok').removeClass('hide');
        }
        else {
            e.parent().addClass('has-warning');
            e.parent().find(".form-control-feedback").addClass('glyphicon-warning-sign').removeClass('glyphicon-ok').removeClass('hide');
        }
    }
}

function formatFileSize(s) {
    s = parseFloat(s);
    if(s<=1024) {
        return "1 ko";
    }
    else {
        s = s/1024;
        if(s<=1024) {
            return Math.round(s) + " ko";
        }
        else {
            s = s/1024;
            return Math.round(s) + " Mo";
        }
    }
}

function getCursorPosition(elem) {
    var el = elem.get(0);
    var pos = 0;
    if('selectionStart' in el) {
        pos = el.selectionStart;
    } else if('selection' in document) {
        el.focus();
        var Sel = document.selection.createRange();
        var SelLength = document.selection.createRange().text.length;
        Sel.moveStart('character', -el.value.length);
        pos = Sel.text.length - SelLength;
    }
    return pos;
}

function setSelectionRange(elem, selectionStart, selectionEnd) {
    elem = elem.get(0);
    if(elem.setSelectionRange) {
        elem.focus();
        elem.setSelectionRange(selectionStart, selectionEnd);
    }
    else if (elem.createTextRange) {
        var range = elem.createTextRange();
        range.collapse(true);
        range.moveEnd('character', selectionEnd);
        range.moveStart('character', selectionStart);
        range.select();
    }
}

function setCursorPosition(elem, pos) {
    setSelectionRange(elem, pos, pos);
}

var PRINT_MOIS_COURT = ['null','janv.','fév.','mars','avril','mai','juin','juil.','août','sept.','oct.','nov.','déc.'];
var PRINT_MOIS = ['null','janvier','février','mars','avril','mai','juin','juillet','août','septembre','octobre','novembre','décembre'];

var PRINT_JOUR_INI = ['D.','L.','Ma.','Me.','J.','V.','S.'];
var PRINT_JOUR_COURT = ['dim.','lun.','mar.','mer.','jeu.','ven.','sam.'];
var PRINT_JOUR = ['dimanche','lundi','mardi','mercredi','jeudi','vendredi','samedi'];

function formatDate(original, originalFormat, destinationFormat, moment) {
    // DEFAULT VALUE
    if(!original) original = "";
    if(!originalFormat) originalFormat = "mysql_datetime";
    if(!destinationFormat) destinationFormat = "datetime";
    if(!moment) moment = "start";
    
    var infos = false;
    if(original!='' && parseInt(original)!=0) {
        switch(originalFormat) {
            case 'date': // "DD/MM/YYYY"
                infos = new Object();
                infos.tm_hour = 0;
                infos.tm_min = 0;
                infos.tm_sec = 0;
                infos.tm_mday = parseInt(original.substr(0,2));
                infos.tm_mon = parseInt(original.substr(3,2));
                infos.tm_year = parseInt(original.substr(6,4));
            break;
            case 'datetime': // "DD/MM/YYYY - HH:MM"
                infos = new Object();
                infos.tm_hour = parseInt(original.substr(13,2));
                infos.tm_min = parseInt(original.substr(16,2));
                infos.tm_sec = 0;
                infos.tm_mday = parseInt(original.substr(0,2));
                infos.tm_mon = parseInt(original.substr(3,2));
                infos.tm_year = parseInt(original.substr(6,4));
            break;
            case 'mysql_date': // "YYYY-MM-DD"
                infos = new Object();
                infos.tm_hour = 0
                infos.tm_min = 0
                infos.tm_sec = 0;
                infos.tm_mday = parseInt(original.substr(8,2));
                infos.tm_mon = parseInt(original.substr(5,2));
                infos.tm_year = parseInt(original.substr(0,4));
            break;
            case 'mysql_datetime': // "YYYY-MM-DD HH:MM:SS"
                infos = new Object();
                infos.tm_hour = parseInt(original.substr(11,2));
                infos.tm_min = parseInt(original.substr(14,2));
                infos.tm_sec = parseInt(original.substr(17,2));
                infos.tm_mday = parseInt(original.substr(8,2));
                infos.tm_mon = parseInt(original.substr(5,2));
                infos.tm_year = parseInt(original.substr(0,4));
            break;
            default:
                return;
        }

        if(originalFormat=="date" || originalFormat=="mysql_date") {
            if(moment=="start") {
                infos.tm_hour = 0;
                infos.tm_min = 0;
                infos.tm_sec = 0;
            }
            else {
                infos.tm_hour = 23;
                infos.tm_min = 59;
                infos.tm_sec = 59;
            }
        }
    }
    else {
        return;
    }
    
    // FORMAT NUMBER
    infos.tm_hour = '%02d'.sprintf(infos.tm_hour);
    infos.tm_min = '%02d'.sprintf(infos.tm_min);
    infos.tm_sec = '%02d'.sprintf(infos.tm_sec);
    infos.tm_mday = '%02d'.sprintf(infos.tm_mday);
    infos.tm_mon = '%02d'.sprintf(infos.tm_mon);
    infos.tm_year = '%04d'.sprintf(infos.tm_year);
                
    switch(destinationFormat) {
        case 'date': // "%d/%m/%Y"
            return infos.tm_mday+"/"+infos.tm_mon+"/"+infos.tm_year;
        break;
        case 'strdate': // "%Y-%m-%d"
            return infos.tm_year+"-"+infos.tm_mon+"-"+infos.tm_mday;
        break;
        case 'datetime': // "%d/%m/%Y - %H:%M"
            return infos.tm_mday+"/"+infos.tm_mon+"/"+infos.tm_year+" - "+infos.tm_hour+":"+infos.tm_min;
        break;
        case 'print_datetime': // "%d/%m/%Y %H:%M"
            return infos.tm_mday+" "+PRINT_MOIS_COURT[parseInt(infos.tm_mon)]+" "+infos.tm_year+" à "+infos.tm_hour+"h"+infos.tm_min;
        break;
        case 'mysql_date': // "%Y-%m-%d"
            return infos.tm_year+"-"+infos.tm_mon+"-"+infos.tm_mday;
        break;
        case 'mysql_datetime': //"%Y-%m-%d %H:%M:%S"
            return infos.tm_year+"-"+infos.tm_mon+"-"+infos.tm_mday+" "+infos.tm_hour+":"+infos.tm_min+":"+infos.tm_sec;
        break;
        case 'timestamp': //timestamp
            return java_mktime(parseInt(infos.tm_year), parseInt(infos.tm_mon), parseInt(infos.tm_mday), parseInt(infos.tm_hour), parseInt(infos.tm_min), parseInt(infos.tm_sec));
        break;
        default:
            return "";
    }
    
}

function getTodayDate(format) {
    let now = new Date();
    return formatDate(now, format);
}

function parseDate(dateStr, format) {
    date = false;
    if(dateStr == "") return date;
    switch(format) {
        case 'yyyy-mm-dd' : { d=dateStr.split("-"); if(d.length==3) date = new Date(d[0], d[1] - 1, d[2]); } break;
        case 'yyyy-dd-mm' : { d=dateStr.split("-"); if(d.length==3) date = new Date(d[0], d[2] - 1, d[1]); } break;
        case 'dd/mm/yyyy' : { d=dateStr.split("/"); if(d.length==3) date = new Date(d[2], d[1] - 1, d[0]); } break;
        case 'mm/dd/yyyy' : { d=dateStr.split("/"); if(d.length==3) date = new Date(d[2], d[0] - 1, d[1]); } break;
    }
    return date;
}

function formatDate(date, format) {
    dateStr = '';
    if(!date instanceof Date || !date>0) return dateStr;
    var yyyy = date.getFullYear();
    var mm = String(date.getMonth()+1).padStart(2, "0");
    var dd = String(date.getDate()).padStart(2, "0");
    switch(format) {
        case 'yyyy-mm-dd' : dateStr = yyyy+"-"+mm+"-"+dd; break;
        case 'yyyy-dd-mm' : dateStr = yyyy+"-"+dd+"-"+mm; break;
        case 'dd/mm/yyyy' : dateStr = dd+"/"+mm+"/"+yyyy; break;
        case 'mm/dd/yyyy' : dateStr = mm+"/"+dd+"/"+yyyy; break;
    }
    return dateStr;
}

function switchDateFormat(dateStr, fromFormat, toFormat) {
    var date = parseDate(dateStr, fromFormat);
    if(!date instanceof Date || !date>0) return '';
    return formatDate(date, toFormat);
}

function java_mktime(year, month, day, hour, minutes, secondes) {
    return new Date(year, month - 1, day, hour, minutes, secondes, 0).getTime() / 1000;
}

function getNbJourOuvrePeriode(d,f) {
    var nbj = 0;
    
    if(d.isSame(f) && !d.isFerie() && d.day()!=0 && d.day()!=6) nbj=1;
    else {
        while(d.isBefore(f)) {
            if(!d.isFerie() && d.day()!=0 && d.day()!=6) nbj++;
            d.add(1, 'days');
        }
        if(!f.isFerie() && f.day()!=0 && f.day()!=6) nbj++;
    }
    return nbj;
}

function rgb2hex(rgb) {
    if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;

    rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
    function hex(x) {
        return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}

function nl2br (str, is_xhtml) {   
    var breakTag = (is_xhtml || typeof is_xhtml === 'undefined') ? '<br />' : '<br>';    
    return (str + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1'+ breakTag +'$2');
}

function replaceAll(string, find, replace) {
    return string.replace(new RegExp(find, 'g'), replace);
}

// VALIDATION

function validateEmail(email) {
    if(email.length<6) return false;
    var emailReg = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,4})?$/;
    if( !emailReg.test( email ) ) {
        return false;
    }
    else {
        return true;
    }
}

function validatePwd(p, minLength, minUpperCase, minLowerCase, minNumber, minSpecial) {
    var anUpperCase = /[A-Z]/;
    var aLowerCase = /[a-z]/; 
    var aNumber = /[0-9]/;
    var aSpecial = /[!|@|#|$|%|^|&|*|(|)|-|_]/;

    if(p.length < minLength) return false;

    var numUpper = 0;
    var numLower = 0;
    var numNums = 0;
    var numSpecials = 0;
    for(var i=0; i<p.length; i++){
        if(anUpperCase.test(p[i]))
            numUpper++;
        else if(aLowerCase.test(p[i]))
            numLower++;
        else if(aNumber.test(p[i]))
            numNums++;
        else if(aSpecial.test(p[i]))
            numSpecials++;
    }

    if(numUpper < minUpperCase || numLower < minLowerCase || numNums < minNumber || numSpecials < minSpecial) return false;
    
    return true;
}

function validateNumSecu(txt) {
    var result = new Object();
    result.ipt = txt;
    while(txt.indexOf(' ')>0) txt = txt.replace(' ','');
    result.filtre = txt;
    result.test = false;
    result.parse = new Object();
    result.format = "";
    result.error = false;
    
    if(txt.length>=0) {
        var sexTxt = txt.substring(0,1);
        var sex = parseInt(sexTxt);
        result.parse.sex = sexTxt;
        result.rest = txt;

        if(sex==1 || sex==2 || sex==3 || sex==4 || sex==7 || sex==8) { // TEST SEX => 1er chiffre = 1(M), 2(F), 3(M-entranger en cours) ou 4(F-entranger en cours), 7(M-temp), 8(F-temp)
            result.format = sexTxt + " ";
            result.rest = txt.substring(1);
            
            if(txt.length>=3) {
                var annee = txt.substr(1,2);
                result.parse.annee = annee;

                if(annee.indexOf("A")==-1 && annee.indexOf("B")==-1) {
                    result.format = result.format + annee + " ";
                    result.rest = txt.substring(3);
                    
                    if(txt.length>=5) {
                        var moisTxt = txt.substr(3,2);
                        var mois = parseInt(moisTxt);
                        result.parse.mois = moisTxt;

                        if(mois>=1 && mois<=12) { // TEST MOIS => 4 + 5ème chiffre entre 1 & 12
                            result.format = result.format + moisTxt + " ";
                            result.rest = txt.substring(5);
                            
                            if(txt.length>=10) {

                                // A: FRANCAIS METROPOLE
                                var deptA = txt.substr(5,2); // de 01 à 95 ou 2A ou 2B
                                var comAtxt = txt.substr(7,3);
                                var comA = parseInt( comAtxt ); // de 001 à 990
                                // B: FRANCAIS OUTREMER
                                var deptBtxt = txt.substr(5,3);
                                var deptB = parseInt( deptBtxt ); // de 970 à 989 
                                var comBtxt = txt.substr(8,2);
                                var comB = parseInt( comBtxt ); // de 01 à 90
                                // C: FRANCAIS NE A L'ETRANGER
                                var deptCtxt = txt.substr(5,2);
                                var deptC = parseInt( deptCtxt ); // = 99 
                                var comCtxt = txt.substr(7,3);
                                var comC = parseInt( comCtxt ); // de 001 à 990

                                result.error = 'deptCom';
                                if( ((parseInt(deptA)>0 && parseInt(deptA)<=95) || deptA=='2A' || deptA=='2B') && ( comA>0 && comA<=990 ) ) { // TEST DEPT/COM A
                                    result.error = false;
                                    result.parse.deptCom = "a";
                                    result.parse.dept = deptA;
                                    result.parse.com = comAtxt;

                                    result.format = result.format + deptA + " " + comAtxt + " ";
                                }
                                else if( (deptB>=970 && deptB<=989) && ( comB>0 && comB<=90 ) ) { // TEST DEPT/COM B
                                    result.error = false;
                                    result.parse.deptCom = "b";
                                    result.parse.dept = deptBtxt;
                                    result.parse.com = comBtxt;

                                    result.format = result.format + deptBtxt + " " + comBtxt + " ";
                                }
                                else if( deptC==99 && ( comC>0 && comC<=990 ) ) { // TEST DEPT/COM C
                                    result.error = false;
                                    result.parse.deptCom = "c";
                                    result.parse.dept = deptCtxt;
                                    result.parse.com = comCtxt;

                                    result.format = result.format + deptCtxt + " " + comCtxt + " ";
                                }

                                if(!result.error) { // RESULT TEST DEPT/COM
                                    result.rest = txt.substring(10);
                                    
                                    if(txt.length>=13) {

                                        var naisTxt = txt.substr(10,3);
                                        var nais = parseInt( naisTxt );
                                        result.parse.nais = naisTxt;

                                        result.error = 'naissance';
                                        if(nais>=1 && nais<=999) { // TEST NAISSANCE
                                            result.format = result.format + naisTxt + " ";
                                            result.rest = txt.substring(13);
                                            
                                            if(txt.length==15) {
                                                var keyTxt = txt.substr(13,2);
                                                var key = parseInt( keyTxt );
                                                result.parse.key = keyTxt;

                                                var nir = txt.substr(0,13);
                                                result.parse.nirTxt = nir;

                                                if(nir.indexOf("A")>0) nir = parseInt( nir.replace('A','0') ) - 1000000;
                                                else if(nir.indexOf("B")>0) nir = parseInt( nir.replace('B','0') ) - 2000000;
                                                else nir = parseInt( nir );
                                                result.parse.nir = nir;

                                                result.parse.correctKey = 97-(nir%97);

                                                if( key==result.parse.correctKey ) {
                                                    result.format = result.format + keyTxt;
                                                    result.test = true;
                                                    result.rest = "";
                                                }
                                                else result.error = 'key';   
                                            }
                                            else result.error = 'length';
                                        }
                                        else result.error = 'naissance';
                                    }
                                    else result.error = 'length';
                                }
                                else result.error = 'deptCom';
                            }
                            else result.error = 'length';
                        }
                        else result.error = 'mois';
                    }
                    else result.error = 'length';
                }
                else result.error = 'annee';
            }
            else result.error = 'length';
        }
        else result.error = 'sex';
    }
    else result.error = 'length';
    
    return result;
}

function validateNumCS(txt) {
    var result = new Object();
    
    result.ipt = txt;
    while(txt.indexOf(' ')>0) txt = txt.replace(' ','');
    result.filtre = txt;
    
    result.test = false;
    
    result.format = "";
    result.rest = txt;
    
    result.error = false;
    
    if(!txt.length>=1) result.error = 'length';
    else {
        
        var l = txt.substr(0,1);
        var regex = new RegExp(/([^A-Za-z\-])/);
        
        if (regex.test (l)) result.error = 'l';
        else {
            result.format = l.toUpperCase();
            result.rest = txt.substr(1);
            
            regex = new RegExp(/([^0-9\-])/);
            if(txt.length>1 && regex.test (result.rest)) result.error = 'caract';
            else {
                if(!txt.length>=3) result.error = 'length';
                else {
                    result.format = result.format + " " + txt.substr(1,2);
                    result.rest = txt.substr(3);
                    
                    if(!txt.length>=5) result.error = 'length';
                    else {
                        result.format = result.format + " " + txt.substr(3,2);
                        result.rest = txt.substr(5);
                        
                        if(txt.length!=7) result.error = 'length';
                        else {
                            result.format = result.format + " " + txt.substr(5,2);
                            result.rest = "";
                            result.test = true;
                        }
                    }
                }
            }
        }
    }
    
    return result;
}

function validateNumCNI(txt) {
    var result = new Object();
    
    result.ipt = txt;
    txt = txt.replace(new RegExp(' ', 'g'), '');
    result.filtre = txt;
    
    result.test = false;
    
    result.format = "";
    result.rest = txt;
    
    result.error = false;
    
    if(txt.length<2) result.error = 'length';
    else {
        // ANNEE
        var annee = txt.substr(0,2);
        result.annee = annee;
        
        var regex = new RegExp(/([^0-9\-])/);
        if(regex.test(annee)) result.error = 'annee';
        else {
            result.annee = parseInt(annee);
            result.format = annee;
            result.rest = txt.substr(2);
            
            if(txt.length<4) result.error = 'length';
            else {
                // MOIS
                var moisTxt = txt.substr(2,2);
                var mois = parseInt(moisTxt);
                result.mois = moisTxt;

                if(!(mois>=1 && mois<=12) || regex.test(mois)) result.error = 'mois';
                else {
                    result.format = result.format + " " + moisTxt;
                    result.rest = txt.substr(4);
                    
                    // DEPT
                    if(txt.length<6) result.error = 'length';
                    else {
                        var deptTxt = txt.substr(4,2).toUpperCase();
                        var dept = parseInt(deptTxt);
                        result.dept = deptTxt;

                        if(!((dept>=1 && dept<=95) || deptTxt=="2A" || deptTxt=="2B" || dept==97)) result.error = 'dept';
                        else {
                            result.format = result.format + " " + deptTxt;
                            result.rest = txt.substr(6);
                            
                            // SERVICE
                            if(txt.length<7) result.error = 'length';
                            else {
                                var srvTxt = txt.substr(6,1);
                                result.srv = srvTxt;
                                result.format = result.format + " " + srvTxt;

                                result.rest = txt.substr(7);
                                
                                // NUM ATTRIB
                                if(txt.length<12) result.error = 'length';
                                else {
                                    var attribTxt = txt.substr(7,5);

                                    if(regex.test(attribTxt)) result.error = 'attrib';
                                    else {
                                        result.format = result.format + " " + attribTxt;
                                        result.rest = txt.substr(12);
                                        
                                        // KEY
                                        if(txt.length!=13) result.error = 'length';
                                        else {
                                            var key = txt.substr(12,1);
                                            result.key = key;
                                            var correctKey = calculCNIkey(result.format);
                                            result.correctKey = correctKey;
                                            
                                            if(regex.test(key) || parseInt(key)!=correctKey) result.error = 'key';
                                            else {
                                                result.format = result.format + " " + key;
                                                result.rest = "";
                                                result.test = true;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    return result;
}

function calculCNIkey(cniFormat) {
    var cni = cniFormat.replace(new RegExp(' ', 'g'), '');
    var factors = [7, 3, 1];
    var result = 0;
    
    
    var regex = new RegExp(/([0-9\-])/);
    
    for(var i=0 ; i<cni.length ; i++) {
        var char = cni.substr(i,1);
        var conv = 0;
        
        if(regex.test(char)) { // CHIFFRE
            conv = parseInt(cni.substr(i,1));
        }
        else { // LETTRE
            conv = char.charCodeAt(0) - 55;
        }
        result += conv * factors[i % 3];
    }
    return result % 10;
}

function validateNumPasseport(txt) {
    var result = new Object();
    
    result.ipt = txt;
    txt = txt.replace(new RegExp(' ', 'g'), '');
    result.filtre = txt;
    
    result.test = false;
    
    result.format = "";
    result.rest = txt;
    
    result.error = false;
    
    if(txt.length<2) result.error = 'length';
    else {
        // 1er NUM
        var num1 = txt.substr(0,2);
        result.num1 = num1;
        
        var regexChiffres = new RegExp(/([^0-9\-])/);
        var regexLettres = new RegExp(/([^A-Z\-])/);
        
        if(regexChiffres.test(num1)) result.error = 'num1';
        else {
            result.format = num1;
            result.rest = txt.substr(2);
            
            if(txt.length<4) result.error = 'length';
            else {
                // LETTRE
                var letter = txt.substr(2,2).toUpperCase();;
                result.letter = letter;

                if(regexLettres.test(letter)) result.error = 'letter';
                else {
                    result.format = result.format + " " + letter;
                    result.rest = txt.substr(4);
                    
                    // 2ème NUM
                    if(txt.length<7) result.error = 'length';
                    else {
                        var num2 = txt.substr(4,3);
                        result.num2 = num2;

                        if(regexChiffres.test(num2)) result.error = 'num2';
                        else {
                            result.format = result.format + " " + num2;
                            result.rest = txt.substr(7);
                            
                            // 3ème NUM
                            if(txt.length!=9) result.error = 'length';
                            else {
                                var num3 = txt.substr(7,2);
                                result.num3 = num3;

                                if(regexChiffres.test(num3)) result.error = 'num3';
                                else {
                                    result.format = result.format + " " + num3;
                                    result.rest = "";
                                    result.test = true;
                                    
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    return result;
}

function basename(path, suffix) {
  var b = path;
  var lastChar = b.charAt(b.length - 1);

  if (lastChar === '/' || lastChar === '\\') {
    b = b.slice(0, -1);
  }

  b = b.replace(/^.*[\/\\]/g, '');

  if (typeof suffix === 'string' && b.substr(b.length - suffix.length) == suffix) {
    b = b.substr(0, b.length - suffix.length);
  }

  return b;
}

// GENERATE PASSWORD

function generatePassword(length,uppercase,numbers,punction) {
  
    var sPassword = "";          
  
    for (i=1; i <= length; i++) {
  
        numI = getRandomNum();
        if ((punction == 0 && checkPunc(numI)) || (numbers == 0 && checkNumber(numI)) ||(uppercase == 0 && checkUppercase(numI))) {i -= 1;}
        else {sPassword = sPassword + String.fromCharCode(numI);}
    }
      
    return sPassword;
}
  
function getRandomNum() {
    // between 0 - 1
    var rndNum = Math.random()
    // rndNum from 0 - 1000
    rndNum = parseInt(rndNum * 1000);
    // rndNum from 33 - 127
    rndNum = (rndNum % 94) + 33;
    return rndNum;
}
  
function checkPunc(num) {
    if (((num >=33) && (num <=47)) || ((num >=58) && (num <=64))) { return true; }
    if (((num >=91) && (num <=96)) || ((num >=123) && (num <=126))) { return true; }
    return false;
}
 
function checkNumber(num) {
    if ((num >=48) && (num <=57)) { return true; }
    else { return false; }
}
 
function checkUppercase(num) {
    if ((num >=65) && (num <=90)) { return true; }
    else { return false; }
}

function copyTextToClipboard(text) {
    $("body").append("<input type='text' id='temp' style='position:absolute;opacity:0;'>");
    $("#temp").val(text).select();
    document.execCommand("copy");
    $("#temp").remove();
}

function copyHTMLToClipboard(htmlText) {
    var copyDiv = document.createElement('div');
    copyDiv.contentEditable = true;
    document.body.appendChild(copyDiv);
    copyDiv.innerHTML = htmlText;
    copyDiv.unselectable = "off";
    copyDiv.focus();
    document.execCommand('SelectAll');
    document.execCommand("Copy", false, null);
    document.body.removeChild(copyDiv);
}

// TABLE SORTABLE
var tableSortableFixHelper = function(e, ui) {
	ui.children().each(function() {
		$(this).width($(this).width());
	});
	return ui;
};

// PHOTO FORM
function initPhotoForm(div, calbckURL, defaultPhotoURL) {
    var photoPreview = div.find("div.photoPreview");
    var photoIptFile = div.find("input[name=photoFile]");
    var btnResetPhoto = div.find("button.btnResetPhoto");
    
    // OPEN FILE EXPLORER
    photoPreview.unbind('click').click( function(event) {
        event.preventDefault();
        photoIptFile.click();
    });
    
    // AUTO UPLOAD ON FILE CHANGE
    photoIptFile.change( function() {
        oldFile = $(this).attr("file");
        file = $(this)[0].files[0];
        if(typeof(file)=="undefined") return false;
        type = file.type;
        name = file.name;
        size = formatFileSize(file.size);

        if(type=="image/png" || type=="image/jpeg" || type=="image/jpg") {
            photoPreview.css('background-image',"url(img/wait.svg)");
            uploadTmpPhotoFile(div, file, oldFile, calbckURL);
        }
        else {
            alert("ERREUR : format de fichier non-admis... ("+type+")");
        }
    });
    
    // RESET PHOTO
    btnResetPhoto.click( function(e) {
        e.preventDefault();
        
        photoIptFile.attr("file", "").attr("nom", "");
        photoPreview.css('background-image', "url('"+defaultPhotoURL+"')");
        btnResetPhoto.addClass('hide');
    });
}

function uploadTmpPhotoFile(div, file, oldFile, calbckURL) {
    if(file.size>0) {
        var photoPreview = div.find("div.photoPreview");
        var photoIptFile = div.find("input[name=photoFile]");
        var btnResetPhoto = div.find("button.btnResetPhoto");
        
        var data = new FormData();
        data.append('action', 'upload_tmp_file');
        data.append('tmp_file', file);
        data.append('old_file', oldFile);
        data.append('nohist', true);

        $.ajax({
            url: calbckURL,
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            type: 'POST',
            success: function(txt){
                if(txt=="error") {
                    alert("ERREUR : un problème est survenue durant le chargement de la photo...");
                }
                else {
                    datas = JSON.parse(txt);
                    
                    photoIptFile.attr("file", datas.dir+datas.tmp).attr("nom", datas.tmp);
                    photoPreview.css('background-image', "url('"+datas.prw+"&size=230')");
                    btnResetPhoto.removeClass('hide');
                }
            }
        });
    }
}

function getUrlParameters() {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        params = [],
        i;
    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');
        params[sParameterName[0]] = (sParameterName[1] === undefined) ? true : decodeURIComponent(sParameterName[1]);
    }
    return params;
}

function getUrlParameter(sParam) {
    var sPageURL = window.location.search.substring(1),
        sURLVariables = sPageURL.split('&'),
        sParameterName,
        i;

    for (i = 0; i < sURLVariables.length; i++) {
        sParameterName = sURLVariables[i].split('=');

        if (sParameterName[0] === sParam) {
            return sParameterName[1] === undefined ? true : decodeURIComponent(sParameterName[1]);
        }
    }
    return false;
}

function beep(duration, frequency, volume, type, callback) {
    var audioCtx = new (window.AudioContext || window.webkitAudioContext || window.audioContext);
    var oscillator = audioCtx.createOscillator();
    var gainNode = audioCtx.createGain();
    
    oscillator.connect(gainNode);
    gainNode.connect(audioCtx.destination);
    
    if(volume) gainNode.gain.value = volume;
    if(frequency) oscillator.frequency.value = frequency;
    if(type) oscillator.type = type;
    if(callback) oscillator.onended = callback;
    
    oscillator.start(audioCtx.currentTime);
    oscillator.stop(audioCtx.currentTime + ((duration || 500) / 1000));
}

function round_number(number, decimals) {
    if(!decimals>0) return Math.round(number);
    number = parseFloat(number);
    mux = decimals * 10;
    n = Math.round(number * mux);
    return n / mux;
}

function number_format(number, decimals, dec_point, thousands_sep) {
  number = (number + '')
    .replace(/[^0-9+\-Ee.]/g, '');
  var n = !isFinite(+number) ? 0 : +number,
    prec = !isFinite(+decimals) ? 0 : Math.abs(decimals),
    sep = (typeof thousands_sep === 'undefined') ? '' : thousands_sep,
    dec = (typeof dec_point === 'undefined') ? '.' : dec_point,
    s = '',
    toFixedFix = function(n, prec) {
      var k = Math.pow(10, prec);
      return '' + (Math.round(n * k) / k)
        .toFixed(prec);
    };
  // Fix for IE parseFloat(0.55).toFixed(0) = 0;
  s = (prec ? toFixedFix(n, prec) : '' + Math.round(n))
    .split('.');
  if (s[0].length > 3) {
    s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep);
  }
  if ((s[1] || '')
    .length < prec) {
    s[1] = s[1] || '';
    s[1] += new Array(prec - s[1].length + 1)
      .join('0');
  }
  return s.join(dec);
}
