var isProcessing;
//Permet aux composant de mutualiser leurs appels
var componentQueue = {};

$(document).ready(function(){

	if(localStorage.getItem('configuration') !== null){
		//Le local storage a été mis à jour lors de la connexion
		var inactivityDelay = JSON.parse(localStorage.getItem('configuration')).inactivityDelay;

		//On est bien dans le cadre d'une conf de gestion de l'inactivité utilisateur
		if(inactivityDelay !== null){
			var timeout;

			//Durée d'affichage (en sec) du message pendant laquelle on peut éviter la déco
			var messageTime = 58;

			//Conversion en milli secondes pour $.message et settimeout
			var messageTimeMilliseconds = messageTime * 1000;

			//On s'assure de travailler avec des entiers
			inactivityDelay = parseInt(inactivityDelay);

			//Controle de valeur délai min à 60 sec
			inactivityDelay = inactivityDelay < 60 ? 60 : inactivityDelay;

			//Déclaration du compteur;
			var inactivityCounter;

			//Gestion de l'activité de l'utilisateur durant l'affichage du message toast
			var userActive = false;

		   $(document).on('mousemove',function(){
		   	//L'utilisateur est actif, permet de savoir s'il a bougé durant l'affichage du message et donc de savoir si on le déco ou pas
		   	userActive = true;

		   	//Si l'utilisateur bouge pendant que le message est affiché
		   	//Alors on réinitialise l'activité du user et on efface les toasts
		   	if($('.toast.inactivity_message').is(':visible')){
		   		core_initialize_activity();
		   		clearTimeout(timeout);
		   	}

		   	//Si l'utilisateur bouge on arrete l'exécution du compteur
		      clearInterval(inactivityCounter);

		      //On réinitialise le compteur avec le délai d'inactivité
		      var countdown = inactivityDelay - messageTime;

		      //Le compteur s'exécute tant que l'utilisateur ne bouge pas
		      inactivityCounter = setInterval(function(){
		      	//Décompte du nombre de sec restantes pour éviter la déco
		         countdown--;

		         //Déclenchement de l'affichage du toast informant de la déco imminente
		         if(countdown === 0){
		         	$.message('warning','Votre session va expirer, vous allez être déconnecté.',messageTimeMilliseconds,'inactivity_message');
		         	userActive = false;
		         	//A la fin du message
		         	timeout = setTimeout(function(){
		         		//Si l'utilisateur a été actif on réinitialise son activité
		         		//Sinon on le déco
		         		if(userActive){
		         			core_initialize_activity();
		         		}else{
		         			core_logout();
		         		}
		         	},messageTimeMilliseconds);
		         }
		      }, 1000);
		   }).mousemove();
		}
	}



	if($.urlParam('title')!=null) window.parent.document.title = decodeURI($.urlParam('title'));
	if($('.login-request').length) $('#login-dropdown').remove();

	var page = $.page();
	page = page == '' ? 'index' : page;
	var init = 'init_'+page;
	init = init.replace(/[^a-z_0-9]/g,'_');

	init_components();

	if($.urlParam('module')==null){
		if(window[init]!=null) window[init]($.urlParam());
	} else {
		var mod = $.urlParam('module').replace(/[^a-z_0-9]/g,'_');
		var init = 'init_plugin_'+mod;
		if(window[init]!=null) window[init]($.urlParam());
	}

	//SHOW HTTP ERROR/NOTICE
	if($.urlParam('error') != null) {
		$.message('error', decodeURIComponent($.urlParam('error')), 0);
		$.urlParam('error', false);
	}
	if($.urlParam('warning') != null) {
		$.message('warning', decodeURIComponent($.urlParam('warning')), 0);
		$.urlParam('warning', false);
	}
	if($.urlParam('info') != null) {
		$.message('info', decodeURIComponent($.urlParam('info')));
		$.urlParam('info', false);
	}
	if($.urlParam('success') != null) {
		$.message('success', decodeURIComponent($.urlParam('success')));
		$.urlParam('success', false);
	}

    //Icône menu mobile
    $('#mainMenu > button').on('click', function(e){
    	$('.menu').toggleClass('open');
    });
    $('.navbar-toggler').on('click', function(e){
    	if($(e.target).closest('#mainMenu').length) return;
    	$('#navbarCollapse').collapse('hide');
    	$('.menu').removeClass('open');
    });

    //Positionnement du loginHeader
	if($(document).width() <= 767) $('#mainMenu .navbar-brand').after($('#loginHeader').detach());
});

//Changement positionnement loginHeader
//au redimensionnement de la fenêtre
$(window).resize(function(event) {
	if(is_phone()) return;
	var width = $(document).width();
	var loginForm = $('#loginHeader').detach();

	if(width>767) $('#navbarCollapse').append(loginForm);
	if(width<=767) $('#mainMenu .navbar-brand').after(loginForm);
});


/** BACK TO TOP **/
$('#scroll-top').click(function() {
	scroll_top(150);
});
// Affichage du bouton dès lors où l'on a scrollé
$(window).on('scroll', function(){
	scrollPos = $(document).scrollTop();
	if (scrollPos >= 100) {
		$('#scroll-top').addClass('active');
	} else {
		$('#scroll-top').removeClass('active');
	}
});
//Permet de scroller en haut de page
function scroll_top(time){
	$('html,body').animate({scrollTop:0},time);
}

/** CONTRÔLES DATE ET HEURE **/
function is_valid_date(string){
	var format = /^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$/;
	return format.test(string);
}
function is_valid_hour(string){
	var format = /^(?:\d|[01]\d|2[0-3]):[0-5]\d$/;
	return format.test(string);
}

//SHOW/HIDE PASSWORD
function toggle_password(element){
	event.stopPropagation();
	var element = $(element);
	element.prev('input').attr('type', (element.hasClass('fa-eye-slash') ? 'text' : 'password'));
	element.toggleClass('fa-eye fa-eye-slash');
}

/** QUICKFORM **/
function reset_quickform_modal(){
	$('.modal form').attr('data-id','');
	$('input, textarea', '.modal').each(function(i, v){
		if($(v).attr('type') == 'checkbox')
			$(v).prop('checked', false);
		else
			$(v).val('');
	});
}

/** CORE **/
//LOGIN
$(document).ready(function(){
	$('body').on('keyup', '.login-form input', function(e){
		if(e.keyCode == 13){
			var button = $(this).closest('.login-form').find('.btn-login');
			core_login(button);
		}
	});
});
function core_login(element){
	if(isProcessing) return;
	var btn = $(element);
	btn.addClass('btn-preloader');

	var form = btn.closest('.login-form');
	var data = form.toJson(true);
	data.redirect = form.attr('data-redirect');
	data.url = form.attr('data-url');
	data.action = 'core_login';

	isProcessing = true;
	$.action(data
	,function(r){
		isProcessing = false;
		if(r.inactivityDelay)
			localStorage.setItem('configuration',JSON.stringify({'inactivityDelay' : parseInt(r.inactivityDelay)}));
		if(r.redirect) window.location = r.redirect;
	},function(r){
		isProcessing = false;
		$('[data-password]',form).val('');
	}, function(r){
		isProcessing = false;
	});
}

function core_logout(url){
	$.action({
		action:'core_logout',
		url: url
	},function(r){
		localStorage.setItem('configuration',JSON.stringify({'inactivityDelay' : null}));
		if(r.redirect) window.location = r.redirect;
	});
}

function core_initialize_activity(){
	$.action({
		action:'initialize_activity'
	},function(){
		$('.toast.inactivity_message').remove();
	});
}

// INIT - INDEX
function init_index(){
	$('#loginHeader #login-button').keypress(function(e){
		var key = e.which;
		if(key == 13){
			$('#login-button').click();
			return false;
		}
	});
}

function init_setting(parameter){

	switch(parameter.section){
		case 'plugin':
			core_plugin_search();

			$('.section-plugin').on('change', 'input.toggle', function(){
				var input = $(this);
				var button = input.closest('.activator');
				var label = $('> label', button).detach();
				var value = input.prop('checked');
				if(!value && !confirm("Êtes-vous sûr de vouloir désactiver ce plugin ?\nCela entraînera la suppression de toutes les données associées.")) {
					input.prop('checked',!value);
					button.prepend(label);
					return;
				}
				button.text((!value?'Activer':'Désactiver'))
					  .toggleClass('text-success text-muted')
					  .prepend(label);

				$.action({
					action : 'core_plugin_state_save',
					plugin : input.closest('li').attr('data-id'),
					state: value ? 1 : 0
				}, function(r){
					core_plugin_firm_show();
				}, function(r){
					button.text(value?'Activer':'Désactiver')
						  .toggleClass('text-success text-muted')
						  .prepend(label);
					input.prop('checked',!value);
					core_plugin_firm_show();
				});

			});
		break;
		case 'user':
			core_user_search();
		break;
		case 'firmPlugin':
			core_firm_plugin_search();
		break;
		case 'userfirmrank':
			core_userfirmrank_search();
		break;
		case 'log':
			$('#logs').sortable_table({
				onSort : search_log
			});
		break;

		case 'rank':
			core_rank_search();
		break;

		case 'dictionary':
			core_dictionary_search();
			$('#label').blur(function(){
				if($('#label').val() != '' && $('#slug').val() == ''){
					$('#slug').off('click');
					core_dictionary_slug_proposal($('#label'), $('#parent'));
				}
			});
			$('#slug').off('click');
			$('#slug').on('click', function(){
				if($('#label').val() != '' && $('#slug').val() == '')
					core_dictionary_slug_proposal($('#label'), $('#parent'));
			});
		break;
		case 'right':
			core_right_search();
		break;
		default:
			if(parameter.section!= null){
				var section = parameter.section.replace(/[^a-z_0-9]/g,'_');
				var init = 'init_setting_'+section;
				if(window[init]!=null) window[init]($.urlParam());
			}
		break;
	}
}

/** RIGHT **/
function right_switch(element){
	$(element).closest('tr').find('input').trigger('click');
}

/** FORM **/
function send_form(element){
	var form = $(element).closest('[data-form]');
	var data = $.getForm(form);

	var data = {};

	for(var key in form.data()){
		if(key!="action" &&  key != "id") continue;
		data[key] = form.attr('data-'+key);
	}

	$('input,select,textarea',form).each(function(i,element){
		element = $(element);
		if(element.attr('data-id')!=null && element.attr('data-id')!=""){
			if(element.attr("type")=='checkbox' || element.attr("type")=='radio'){
				data[element.attr('data-id')] = (element.is(':checked')?1:0);
			}else{
				data[element.attr('data-id')] = element.val();
			}
		}
	});
	data.action = 'send_form';
	$.action(data,function(r){
	});
}


/** LOG **/
// SEARCH
function search_log(exportMode, callback){
	if(isProcessing) return;
	var box = new FilterBox('#filters');
	if(exportMode) $('#export-logs-btn').addClass('btn-preloader');

	isProcessing = true;
	$('#logs').fill({
		action:'core_search_log',
		filters: box.filters(),
		sort: $('#logs').sortable_table('get'),
		export: !exportMode ? false : exportMode,
	},function(){
		isProcessing = false;
		if(callback!=null) callback();
	},function(){
		isProcessing = false;
	});
}

/** USER FIRM RANK**/
// SEARCH
function core_userfirmrank_search(callback){
	$('#userfirmranks').fill({
		firm : $('#firm').val(),
		action:'core_userfirmrank_search'
	},function(){
		if(callback!=null) callback();
	});
}

// SAVE
function core_user_savefirmrank(element){
	if(isProcessing) return;
	var button = $(element);
	var data = $.getForm('#userfirmrankForm');
	data.id = $('#userfirmrankForm').attr('data-id');
	button.html('<i class="fas fa-spin fa-spinner"></i> Enregistrement en cours').addClass('disabled');
	isProcessing = true;
	$.action(data,function(r){
		button.html('<i class="fas fa-check"></i> Enregistrer').removeClass('disabled');
		if(typeof r.success !== 'undefined'){
			for(var i = 0; i<r.success.length; i++)
				$.message('success',r.success[i]);
		}
		if(typeof r.warning !== 'undefined'){
			for(var i = 0; i<r.warning.length; i++)
				$.message('warning',r.warning[i]);
		}

		$('#userfirmrankForm').attr('data-id','');
		$('#userfirmrankForm input').val('');
		init_components('#userfirmrankForm');
		$('#firm').val($("#firm option:first").val());
		$('#rank').val($("#rank option:first").val());
		isProcessing = false;
		core_userfirmrank_search();
	});
}

// EDIT
function core_userfirmrank_edit(element){
	var form = $('#userfirmrankForm');
	var line = $(element).closest('tr');

	$.action({
		action:'core_userfirmrank_edit',
		id:line.attr('data-id')
	},function(r){
		$.setForm(form,r);
		$('#firm').change();
		init_components(form);
		form.attr('data-id',r.id);
	});
}

// DELETE
function core_userfirmrank_delete(element){
	if(isProcessing) return;
	if(!confirm('Êtes vous sûr de vouloir supprimer ce lien Établissement / Utilisateur / Rang ?')) return;
	var line = $(element).closest('tr');

	isProcessing = true;
	$.action({
		action : 'core_userfirmrank_delete',
		id : line.attr('data-id')
	},function(r){
		isProcessing = false;
		$.message('info', 'Lien Établissement / Utilisateur / Rang supprimé.')
		line.remove();
	},function(r){
		isProcessing = false;
	});
}

/** FIRM **/
//Récuperation d'une liste  etablissement dans le tableau #firms
function core_firm_search(callback,exportMode){
	if(isProcessing) return;

	var table = $('#firms');
	var box = new FilterBox('#core_firm-filters');
	if(exportMode) $('.btn-export').addClass('btn-preloader');

	isProcessing = true;
	table.fill({
		action:'core_firm_search',
		filters: box.filters(),
		sort: table.sortable_table('get'),
		export:  !exportMode ? false : exportMode
	},function(response){
		isProcessing = false;
		if(!exportMode) $('.results-count > span').text(response.pagination.total);
		if(callback!=null) callback();
	},function(r){
		isProcessing = false;
	});
}

//Ajout ou modification etablissement
function core_firm_save(){
	if(isProcessing) return;

	var form = $('#firm-form');
	var data = form.toJson();
	isProcessing = true;
	$.action(data,function(r){
		isProcessing = false;

		form.attr('data-id',r.id);
		$.urlParam('id',r.id);
		$.message('success','Enregistré');
	},function(r){
		isProcessing = false;
	});
}

//Suppression établissement
function core_firm_delete(element){
	if(!confirm('Êtes-vous sûr de vouloir supprimer cet établissement ?') || isProcessing) return;

	var line = $(element).closest('.item-line');
	isProcessing = true;
	$.action({
		action: 'core_firm_delete',
		id: line.attr('data-id')
	},function(r){
		isProcessing = false;
		line.remove();
		$.message('info','Établissement supprimé');
	},function(r){
		isProcessing = false;
	});
}

/** FIRM PLUGINS **/
// SEARCH
function core_right_search(callback){
	$('#rights').fill({
		action: 'core_right_search',
		targetUid: $('#targetUid').attr('data-rank'),
		firm: $('#firm').val()
	},function(r){
		update_checkboxes(r);
		if(callback!=null) callback(r);
	});
}

// TOGGLE RIGHT
function core_right_toggle(element){
	var line = $(element).closest('tr');
	$.action({
		action:'core_right_toggle',
		targetUid:$('#targetUid').attr('data-rank'),
		targetScope: 'rank',
		firm:$('#firm').val(),
		scope:line.attr('data-scope'),
		right:$(element).attr('data-right'),
		state:$(element).prop('checked')?1:0
	});
}

// SEARCH
function core_firm_plugin_search(callback){
	$('#firmplugins').fill({
		action: 'core_firm_plugin_search',
		firm: $('#firm').val()
	},function(r){
		update_checkboxes(r);
		if(callback!=null) callback(r)
	});
}

// ENABLE/DISABLE
function core_firm_plugin_save(element){
	var line = $(element).closest('.item');

	$.action({
		action:'core_firm_plugin_save',
		firm :$(element).closest('.firm-item').attr('data-id'),
		state : $(element).prop('checked')?1:0,
		plugin: line.attr('data-id')
	});
}

function update_checkboxes(response){
	$('input[data-result="0"]').prop('checked',false);
	$('input[data-result="1"]').prop('checked',true);
	$('input[data-result="2"]').prop('indeterminate',true);
}
/*
// SUPPRESSION LOGO ÉTABLISSEMENT
function firm_logo_delete(element){
	if(!confirm('Êtes vous sûr de vouloir supprimer l\'image ?')) return;
	var imageComposer = $(element).parent().find("input[data-type='image']");

	$.action({
		action: 'firm_logo_delete',
		id: $('#firm').val()
	}, function(r){
		imageComposer.wrap('<form>').closest('form').get(0).reset();
		imageComposer.unwrap();
		$(element).next('img').attr('src', $(imageComposer).attr('data-default-src'));
		$(element).remove();
	});
}*/

/** USER **/
// SEARCH
function core_user_search(callback){
	$('#users').fill({
		action: 'core_user_search'
	},function(){
		if(callback!=null) callback();
	});
}

// SAVE
function core_user_save(){
	var form = $('#userFormAdmin');
	var data = $.getForm(form);
	data.id = form.attr('data-id');

	$.action(data,function(r){
		$.message('success','Utilisateur enregistré');
		$('#login').removeAttr('readonly');
		$('input',form).val('');
		form.attr('data-id','');
		init_components(form);
		core_user_search();
	});
}

// EDIT
function core_user_edit(element){
    var line = $(element).closest('tr');
    $.action({
        action: 'core_user_edit',
        login: line.attr('data-user')
    },function(r){
        $.setForm('#userFormAdmin',r);
        $('#userFormAdmin').attr('data-id',r.id);
        $('#login').attr('readonly', true);
        $('#password2').val('');
        init_components('#userFormAdmin');
        $('html,body').animate({ scrollTop: 0}, 300);
    });
}


// DELETE
function core_user_delete(element){
	if(!confirm('Êtes vous sûr de vouloir supprimer cet utilisateur ?')) return;
	var line = $(element).closest('tr');
	$.action({
		action : 'core_user_delete',
		login : line.attr('data-user')
	},function(r){
		$.message('info','Utilisateur supprimé');
		$('#userFormAdmin').attr('data-id','');
		reset_inputs($('#userFormAdmin'));
		$('#login').removeAttr('readonly');
		line.remove();
	});
}


/* ACCOUNT **/
function core_account_lost_password(element){
	if(isProcessing) return;
	var btn = $(element);
	btn.addClass('btn-preloader').attr('disabled', true);

	isProcessing = true;
	$.action({
		action: 'core_account_lost_password',
		mail : $('#mail').val()
	}, function(r){
		isProcessing = false;
		$.message('success','Confirmation envoyée par e-mail');
		btn.removeAttr('disabled');
	}, function(r){
		isProcessing = false;
		btn.removeAttr('disabled');
	});
}

function core_account_save(element){
	var data = $('#user-form').toJson();
	data.login =  $('#login').val();
	data.avatar = $('#avatar')[0].files[0];
	data.action =  'core_account_save';

	$.action(data, function(r){
		$('.password-field input').val('');
		$.message('success','Enregistré');
		if(r.warning) $.message('warning',r.warning);
	});
}

function core_account_api_save(element){
	var data = $('#account-api-form').toJson();
	data.action =  'core_account_api_save';

	$.action(data, function(r){
		$.message('success','Enregistré');
	});
}

// SUPPRIME AVATAR USER
function core_account_avatar_delete(element){
	if(!confirm('Êtes vous sûr de vouloir supprimer l\'image ?')) return;
	var imageComposer = $(element).parent().find("input[data-type='image']");

	$.action({
		action: 'core_account_avatar_delete',
		login: $('#login').val()
	}, function(r){
		imageComposer.wrap('<form>').closest('form').get(0).reset();
		imageComposer.unwrap();
		$(element).next('img').attr('src', $(imageComposer).attr('data-default-src'));
		$(element).remove();
	});
}

/** RANKS **/
// SEARCH
function core_rank_search(callback){
	$('#ranks').fill({
		action: 'core_rank_search'
	},function(){
		if(callback!=null) callback();
	});
}

// SAVE
function core_rank_save(){
	var data = $.getForm('#rankForm');
	data.id = $('#rankForm').attr('data-id');
	$.action(data,function(r){
		$.message('success','Rang enregistré');
		$('#rankForm input').val('');
		$('#rankForm').attr('data-id','');
		core_rank_search();
	});
}

// EDIT
function core_rank_edit(element){
	var line = $(element).closest('tr');
	$.action({action:'core_rank_edit',id:line.attr('data-id')},function(r){
		$.setForm('#rankForm',r);
		$('#rankForm').attr('data-id',r.id);
	});
}

// DELETE
function core_rank_delete(element){
	if(!confirm('Êtes vous sûr de vouloir supprimer ce rang ?')) return;
	var line = $(element).closest('tr');
	$.action({
		action : 'core_rank_delete',
		id : line.attr('data-id')
	},function(r){
		$.message('info','Rang supprimé');
		line.remove();
	});
}


/** DICTIONARY **/
// SEARCH
function core_dictionary_search(callback){
	var parentValue = $('#parent').val();
	parentValue != "" ? $('#prev-button').removeClass('hidden') :  $('#prev-button').addClass('hidden');
	$('#dictionnaries').fill({
		action:'core_dictionary_search',
		parent : parentValue
	},function(r){
		reset_inputs($('#dictionaryForm'), false, true);
		if(callback!=null) callback();
		var tpl = $('#parent').find('option[value="{{id}}"]');
		if(!tpl.parent('span').length) tpl.wrap('<span>').addClass('hidden');
	});
}

// SAVE
function core_dictionary_save(){
	var data = $.getForm('#dictionaryForm');
	data.id = $('#dictionaryForm').attr('data-id');
	data.parent = $('#parent').val();
	$.action(data,function(r){
		$.message('success','Liste enregistrée');
		$('#dictionaryForm input').val('');
		$('#dictionaryForm').attr('data-id','');
		core_dictionary_search();
	});
}

// EDIT
function core_dictionary_edit(element){
	var line = $(element).closest('tr');
	$.action({
		action: 'core_dictionary_edit',
		id: line.attr('data-id')
	},function(r){
		$.setForm('#dictionaryForm',r);
		$('#dictionaryForm').attr('data-id',r.id);
	});
}

// DELETE
function core_dictionary_delete(element){
	if(!confirm('Êtes-vous sûr de vouloir supprimer cette liste ?')) return;
	var line = $(element).closest('tr');
	$.action({
		action: 'core_dictionary_delete',
		id: line.attr('data-id')
	},function(r){
		line.remove();
		$.message('info','Liste supprimée');
	});
}

// Remplissage de la liste (select) --> Dans les settings
function get_dictionary_items(elem, elemToFill){
	var parent = $(elem).closest('tr');
	var id = $(parent).attr('data-id');
	var	parentId = $(parent).attr('data-parent');

	$(elemToFill).fill({
		action:'core_dictionary_search',
		parent : parentId.toString()
	},function(){
		$(elemToFill).val(id).change();
	});
}

// Ajout de sous-liste --> Dans les settings
function add_sub_dictionary(elem){
	reset_inputs($('#dictionaryForm'), false, true);

	var parent = $(elem).closest('tr');
	var id = $(parent).attr('data-id');
	var value = parent.find(".itemLabel").text();

	if ($("#parent option[value='"+id+"']").length > 0)
		$('#parent').val(id).change();
	else {
		get_dictionary_items(elem, "#parent");
		$('code').addClass('hidden');
	}
	$('#prev-button').removeClass('hidden');
}

// Récupération éléments de la liste précédente --> Dans les settings
function previous_list_dictionary(elem){
	var selected = $('#parent > option:selected').val();
	reset_inputs($('#dictionaryForm'), false, true);

	$.action({
		action: 'core_dictionary_get_parent',
		selected: selected
	}, function(r){
		var data = r.rows[0];
		$('#parent option[value!="{{id}}"]').remove();

		if (data.parentId == "") $('#prev-button').addClass('hidden');
		if (data.parents[0].parent == "0") {
			$('#parent').append("<option value='' selected>-</option>");
			$('code').removeClass('hidden');
		}

		$.each(data.parents, function (index, value){
			if (value.id == data.parentId)
				$('#parent').append("<option selected value='"+value.id+"'>"+value.label+"</option>");
			else
				$('#parent').append("<option value='"+value.id+"'>"+value.label+"</option>");
		});
		core_dictionary_search();
	});
}

// Récupération des sous-listes pour les champ de type "dictionary" --> Où le module est appelé
function get_sub_dictionary(elem, name, currentDepth){
	var input = $(elem);
	var data = input.data();
	data.output = data.output ? data.output : 'id';
	var selectValue = input.val();
	var optSubLabel = $('option:selected', elem).attr('data-sublabel');
	var depth = (input.attr('data-depth') && input.attr('data-depth') != "") ? input.attr('data-depth') : "1";
	var fieldName = name == '' ? input.attr('name') : name;

	currentDepth -= currentDepth != 1 ? input.nextAll('select').length : 0;
	if(input.closest('span.dictionary-container').length != 0){
		var id = input.nextAll().last().attr('id');
		input.attr('id', id).nextAll().remove();
	}

	if (selectValue.length && currentDepth < depth) {
		input.removeAttr('name');
		currentDepth += 1;

		$.action({
			action: 'core_dictionary_search',
			parent: selectValue
		}, function(r){
			var option = '';
			if(input.closest('span.dictionary-container').length == 0) input.wrap('<span class="dictionary-container"></span>');
			var newSelect = clone_input_dictionary(input, selectValue, fieldName);
			var currentDepth = input.closest('span.dictionary-container').children('select').length;

			if (input.attr('data-disable-label') != "" && optSubLabel != "" && optSubLabel != "null") input.after('<label class="label-select">'+optSubLabel+'</label>');
			newSelect.attr('onchange', 'get_sub_dictionary(this, "'+fieldName+'", '+currentDepth+');');
			newSelect.append('<option value=""> - </option>');

			$.each(r.rows, function(index, value){
				option += '<option value="'+value[data.output]+'" data-parent="'+value.parent+'" data-sublabel="'+value.sublistlabel+'">'+value.label+'</option>';
			});
			newSelect.append(option);
		});
	} else if (!selectValue.length) {
		input.attr('name', fieldName);
	}
}

// Récupération des sous-listes depuis l'id du plus petit enfant --> Où le module est appelé
function get_selected_values(elem, select){
	var input = $(elem);
	var data = input.data();
	data.output = data.output ? data.output : 'id';
	if(input.closest('span.dictionary-container').length == 0) input.wrap('<span class="dictionary-container"></span>');
	var fieldName = input.attr('name');
	var currentDepth = 1+input.closest('span.dictionary-container').children('select').length;
	var optSubLabel = select.sublistlabel;
	var option = '';

	if ( select.childs  &&  select.childs.length > 0) {
		var newSelect = clone_input_dictionary(input, select.id, fieldName);

		if (newSelect.attr('data-disable-label') != "" && optSubLabel != "" && optSubLabel != "null" && optSubLabel != undefined) input.after('<label class="label-select">'+optSubLabel+'</label>');
		newSelect.append('<option value=""> - </option>');
	}
	$.each(select.childs, function(index, value){
		var selected = '';

		if (value.hasOwnProperty("selected")) {
			input.removeAttr('name');
			get_selected_values(newSelect, value);
			selected = "selected";
		}

		newSelect.attr('onchange', 'get_sub_dictionary(this,"'+fieldName+'", '+currentDepth+');');
		option += '<option value="'+value[data.output]+'" data-parent="'+value.parent+'" data-sublabel="'+value.sublistlabel+'" '+selected+'>'+value.label+'</option>';
	});
	if(newSelect) newSelect.append(option);
}

// Clone du select de type "dictionary"
function clone_input_dictionary(input, id, name){
	var newSelect = input.clone();
	input.removeAttr('id').after(newSelect).after(' ');
	newSelect.removeAttr("data-type").removeAttr('name').removeAttr('data-value');
	// newSelect.attr('id', 'children-select-'+id).attr('name', name);
	newSelect.find('option').remove();
	return newSelect;
}

//Rafraîchit la table de la liste donnée
//En lien avec le composant dictionary_table
function dictionary_table_refresh(elem){
	var id = $(elem).attr('data-dictionary');
	var table = $(elem).find('table:eq(0)');
	$.action({
		action: 'core_dictionary_table_search',
		id: id
	},function(r){
		table.find('tbody tr:visible').remove();
		var tpl = table.find('tbody tr:hidden').get(0).outerHTML;
		for(var key in r.rows){
			var row = r.rows[key];
			var line = $(Mustache.render(tpl,row));
			line.removeClass('hidden');
			table.find('tbody').append(line);
		}
	});
}

function core_dictionary_slug_proposal(element, parent){
	var line = $(element).closest('tr');
	$.action({
		action : 'core_dictionary_slug_proposal',
		id : line.attr('data-id'),
		label : $(element).val(),
		parent : $(parent).val()
	},function(response){
		$('#slug').val(response.slug);
	});
}

/** PLUGINS **/
// SEARCH
function core_plugin_search(callback){
	var list = $('#plugins');

	list.fill({
		action:'core_plugin_search'
	},function(){
		init_tooltips(list);
		core_plugin_firm_show();
		$('.firm-toggle').each(function(i,element){
			$(element).prop('checked',$(element).attr('data-value')=='1');
		});
		if(callback!=null) callback();
	});
}

function core_plugin_firm_show(){
	$('#plugins .item').each(function(i,element){
		$('.plugin-firm-block',element).toggleClass('hidden',!$('input.toggle',element).prop('checked'));
	});
}

// RÉCUPÉRATION PARAMÈTRE URL
var get_url_parameter = function get_url_parameter(sParam, string) {
	var sPageURL = !string ? decodeURIComponent(window.location.search.substring(1)) : string;
	var 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 : sParameterName[1];
		}
	}
};

// DROPZONE
function dropzone_delete_file(element){
	if(!confirm('Êtes-vous sûr de vouloir supprimer ce fichier ?')) return;
	var elem = $(element);
	var line = elem.closest('li');

	var container = elem.closest('div[data-type="dropzone"]');
	var inputTemp = container.find('#'+container.attr('id')+'_temporary');

	var values = inputTemp.val().length ? JSON.parse(inputTemp.val()) : [];

	for (var i in values) {
		if(values[i]['path'] == line.attr('data-path'))
			values.splice(i, 1);
	}
	line.remove();
	inputTemp.val(JSON.stringify(values));
}

/* GENERAL SETTINGS */
//Sauvegarde de la configuration générale
function core_general_settings_save(){
	var data = $('#general-settings').toJson();
	data.password_format = $('#password-format-form').attr('data-format');

	$.action(data, function(r){
		$.message('success', 'Configuration enregistrée');
	});
}
function core_general_password_reset_delay(){
    if(!confirm('Êtes-vous sûr de vouloir forcer tous les utilisateurs à réinitialiser leurs mot de passe ?')) return;
    $.action({
        action: 'core_general_password_reset_delay'
    }, function(r){
        $.message('success', 'Validé');
    });
}
function password_settings_format(){
	var patterns = [];
	$('#password-format-form input[data-pattern]:checked').each(function(){
		patterns.push($(this).attr('data-pattern'));
	});
	$('#password-format-form').attr('data-format',JSON.stringify(patterns));
}
//Active/Désactive la page de maintenance du site
function toggle_maintenance(){
	var checkbox = $('#maintenance');
	var state = checkbox.is(':checked') ? 'd\'activer' : 'de désactiver';
	if(!confirm("Vous êtes sur le point "+state+" la page de maintenance du site.\nVoulez-vous continuer ?")){
		checkbox.is(':checked') ? checkbox.removeAttr('checked').prop('checked', false) : checkbox.attr('checked', true).prop('checked', true);
		return;
	}
	core_general_settings_save();
}


/* FUNCTIONS */
//Récupère la plus petite valeur d'un tableau
function getMinValue(arr) {
	return arr.reduce(function (p, v) {
		return ( p < v ? p : v );
	});
};
//Récupère la plus grande valeur d'un tableau
function getMaxValue(arr) {
	return arr.reduce(function (p, v) {
		return ( p > v ? p : v );
	});
};

//Check si la valeur saisie dans l'input
//est une adresse e-mail bien formatée
function is_email(email) {
	var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
	return re.test(String(email).toLowerCase());
}
//Check si la valeur saisie dans
//l'input est une url bien formatée
function is_url(str) {
	regexp =  /^(?:(?:https?|ftp):\/\/)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/\S*)?$/;
	if (regexp.test(str))
		return true;
	return false;
}
//Check format n° de téléphone
function is_phone_number(number, required, label){
	if (required && number == ''){
		$.message('error',label+' obligatoire');
		return false;
	}

	if (number != ''){
		number = number.replace(/\s/g, '');
		number = number.replace(/\./g, '');
		number = number.replace(/-/g, '');
		if(is_numeric(number)) {
			if(/^(?:(?:\+|00)\d{2}|0)\s*[1-9](?:[\s.-]*\d{2}){4}$/.test(number) == false){
				$.message('error',' Le format du n° de '+label.toLowerCase()+' est invalide');
				return false;
			}
		} else {
			$.message('error',' Le n° de '+label.toLowerCase()+' contient des caractères interdits');
			return false;
		}
	}
	return true;
}

//Check si la valeur de l'input est numérique
function is_numeric(n) {
	return !isNaN(parseFloat(n)) && isFinite(n);
}

//Detecte le pourcentage de luminosité d'une couleur au format rgb(r,g,b) ou hexa (#ffffff)
function color_light(color) {

	//format rgb : rgb(255,255,255)
	if(color.indexOf('rgb') !== -1){
		regex = /([0-9]*)[\s|\t]*,[\s|\t]*([0-9]*)[\s|\t]*,[\s|\t]*([0-9]*)[\s|\t]*/gm;
		var  m = regex.exec(color);
		if(!m || m.length<4) return 100;
		var r = m[1];
		var g = m[2];
		var b =  m[3];
	//format hexa : #ffffff
	}else{
		var c = color.substring(1);
		var rgb = parseInt(c, 16);
		var r = (rgb >> 16) & 0xff;
		var g = (rgb >>  8) & 0xff;
		var b = (rgb >>  0) & 0xff;
	}

	var light = 0.2126 * r + 0.7152 * g + 0.0722 * b;
	return Math.round(light * 100 / 255);
}

function number_with_space(number) {
    return number.toLocaleString('fr-FR');
}
function str_price_to_decimal(str){
	return str.replace(/,/g,'.').replace(/ /g,'');
}

//Comme la fonction ucfirst de PHP
function ucfirst(string) {
	return string.charAt(0).toUpperCase() + string.slice(1);
}

//Permet de revenir/rester sur l'onglet courant
//au reload de page, ou au clic sur un lien particulier
if (location.hash) $('a[href="' + location.hash + '"]').tab('show');
var activeTab = localStorage.getItem('activeTab');
if (activeTab && $('a[href="' + activeTab + '"]').lenght) $('a[href="' + activeTab + '"]').tab('show');

$('body').on('click', 'a[data-toggle="tab"]', function(e){
	e.preventDefault();
	var tab_name = this.getAttribute('href');
	history.pushState ? history.pushState(null, null, tab_name) : location.hash = tab_name;
	localStorage.setItem('activeTab', tab_name);

	$(this).tab('show');
	return false;
});


$(window).on('popstate', function () {
	var anchor = location.hash || $('a[data-toggle="tab"]').first().attr('href');
	$('a[data-toggle="tab"][href="' + anchor + '"]').tab('show');
});

//Check si la chaîne de caractères
//fournies est une chaîne JSON
function is_json_string(str) {
	try {
		JSON.parse(str);
	} catch (e) {
		return false;
	}
	return true;
}

//Sélectionne le texte de l'élément passé en paramètre
function select_text(element, event){
	event.stopImmediatePropagation();
	var sel, range;
    var el = $(element).get(0); 						//get element id

    if(window.getSelection && document.createRange) { 	//Browser compatibility
    	sel = window.getSelection();
      	if(sel.toString() == ''){						//no text selection
      		window.setTimeout(function(){
	            range = document.createRange(); 		//range object
	            range.selectNodeContents(el); 			//sets Range
	            sel.removeAllRanges(); 					//remove all ranges from selection
	            sel.addRange(range);					//add Range to a Selection.
        	},1);
    	}
    } else if (document.selection) { 					//older ie
    	sel = document.selection.createRange();
        if(sel.text == ''){ 							//no text selection
            range = document.body.createTextRange();	//Creates TextRange object
            range.moveToElementText(el);				//sets Range
            range.select(); 							//make selection.
        }
    }
}

//Récupère le contenu du texte sélectionné / highlighté
function get_selected_text(element) {
	var elem = element.get(0);
    if(elem.tagName === "TEXTAREA" || (elem.tagName === "INPUT" && elem.type === "text"))
        return elem.value.substring(elem.selectionStart, elem.selectionEnd);
    return null;
}

//Permet de copier le contenu de l'element dans le presse-papier
function copy_string(string,element) {
	var temparea = document.createElement('textarea');
	temparea.value = string;
	temparea.setAttribute('readonly', '');
	temparea.style = {position: 'absolute', left: '-9999px'};
	document.body.appendChild(temparea);
	temparea.select();
	document.execCommand('copy');
	document.body.removeChild(temparea);

   if(element){
   		element = $(element);
	    if(element.data('ui-tooltip')) return;

		element.tooltip({
			items: '*',
		    tooltipClass: 'quickform-tooltip',
		    content: 'Copié dans le presse papier',
		    open: {effect:'fade',duration:750},
		    close: {effect:'fade',duration:750}
		});
		element.tooltip('open');
		setTimeout(function(){element.tooltip('close');element.tooltip('destroy');}, 2000);
	}
}


//Reset des inputs d'un conteneur
function reset_inputs(container, onlyVisible, domData){
	var container = container ? container : $('body');
	var visibility = onlyVisible ? onlyVisible : false;
	var dom = domData ? domData : false;
	if(dom) container.removeAttr('data-id');

	var classicInputs = visibility==true ? $('input:visible, textarea:visible, select:visible', container) : $('input, textarea, select', container);
	classicInputs.each(function(i, v){
		if($(v).attr('type') == 'checkbox')
			$(v).prop('checked', false);
		else
			$(v).val('');
	});

	var customInputs = visibility==true ? $('*[contenteditable="true"]:visible', container) : $('*[contenteditable="true"]', container);
	customInputs.each(function(j,val){
		$(val).text('');
	});
}

//Check si le contenu d'un input est
//selectionné (en surbrillance avec le curseur)
function is_text_selected(input) {
	if (typeof input.selectionStart == "number") {
		return input.selectionStart == 0 && input.selectionEnd == input.value.length;
	} else if (typeof document.selection != "undefined") {
		input.focus();
		return document.selection.createRange().text == input.value;
	}
}

//Renvoie un tableau en ayant supprimé
//toutes les valeurs dupliquées
function only_uniq_values(a) {
	var seen = {};
	var out = [];
	var len = a.length;
	var j = 0;
	for(var i = 0; i < len; i++) {
		var item = a[i];
		if(seen[item] !== 1) {
			seen[item] = 1;
			out[j++] = item;
		}
	}
	return out;
}

//Contrôle éléments saisis dans input de type number.
//Autorise ou non les décimales et les nb négatifs
function input_number_control(e, decimal, relative){
	var authorizedKeys = [
		"Backspace", "Delete", "Tab",
		"ArrowLeft", "ArrowUp", "ArrowRight", "ArrowDown",
		"-", ".", ",",
		"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
	];

	switch (e.key) {
		case ".":
		case ',':
			return decimal?decimal:false;
		break;
		case '-':
			return relative?relative:false;
		break;
		default:
			return (
				((e.key=="a" || e.key=="c" || e.key=="v" || e.key=="z" || e.key=="x") && (e.ctrlKey===true || e.metaKey===true)) ||
				(authorizedKeys.indexOf(e.key) !== -1)
			);
		break;
	}
}
//Permet de checker si la saisie est en majuscule ou non
//Fonction utilisable uniquement dans function callback de listener d'event
function is_caps(){
	e = window.event;
	return is_phone() ? true : (e.shiftKey !== true && e.metaKey !== true) ? (e.getModifierState("CapsLock") ? true : false) : (e.getModifierState("CapsLock") ? false : true);
}

//Check si l'objet est vide ou non
//Retourne true si vide, false sinon
function is_empty_obj(obj) {
	for(var key in obj)
		if(obj.hasOwnProperty(key))  return false;
	return true;
}

//Permet de retourner une propriété d'un
//objet de manière totalement aléatoire
function random_property(obj) {
	var keys = Object.keys(obj)
	return obj[keys[ keys.length * Math.random() << 0]];
}

function get_characters_set() {
	var CHARACTER_SETS = [
		["0123456789"],
		["abcdefghijklmnopqrstuvwxyz"],
		["ABCDEFGHIJKLMNOPQRSTUVWXYZ"],
		["!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"],
	];

	// Concatène les jeux de caractères
	var rawCharset = "";
	CHARACTER_SETS.forEach(function(entry, i) {
		rawCharset += entry[0];
	});

	// Parse en UTF-16, supprime les doublons, convertit en tableau de string
	var charset = [];
	for (var i = 0; i < rawCharset.length; ++i) {
		var c = rawCharset.charCodeAt(i);
		//Check si character UTF-16 valide
		if (c<0xD800 || c>=0xE000) {
			var s = rawCharset.charAt(i);
			if (charset.indexOf(s) == -1) charset.push(s);
			continue;
		}
		if (0xD800<=c && c<0xDC00 && i+1<rawCharset.length) {
			var d = rawCharset.charCodeAt(i + 1);
			if (0xDC00<=d && d<0xE000) {
				var s = rawCharset.substring(i, i+2);
				i++;
				if (charset.indexOf(s) == -1) charset.push(s);
				continue;
			}
		}
		throw "Invalid UTF-16";
	}
	return charset;
}

//Retourne un entier aléatoire dans la plage [0, n)
//(2 méthodes utilisées)
function get_random_int(maxRange) {
	//Récup d'un entier aléatoire via le module Math
	//(fallback si pas de module crypto)
	var x = random_int_math(maxRange);

	//Récupération d'un entier aléatoire via le module crypto
	x = (x + random_int_crypto(maxRange)) % maxRange;
	return x;
}

//Retourne un entier aléatoire
//Peu sécurisé (car calculable) mais
//présent sur tous les navigateurs
function random_int_math(maxRange) {
	var x = Math.floor(Math.random() * maxRange);
	if (x < 0 || x >= maxRange) throw "Arithmetic exception";
	return x;
}

//Retourne un entier aléatoire
//Extrêmement sécurisé, mais pas
//disponible sur tous les navigateurs
//+ d'infos ici: https://developer.mozilla.org/fr/docs/Web/API/RandomSource/getRandomValues
function random_int_crypto(maxRange) {
	var cryptoObject = null
	if ("crypto" in window) {
		//Check si le module crypto est disponible (Chrome, Firefox, Safari)
		cryptoObject = crypto;
	} else if ("msCrypto" in window) {
		//Check si le module crypto est disponible (Edge, IE)
		cryptoObject = msCrypto;
	}

	//Check + récupération propriétés/fonctions nécessaires du module crypto
	if ("getRandomValues" in cryptoObject && "Uint32Array" in window && typeof Uint32Array == "function") {
		//Génère un échantillon impartial/aléatoire
		var x = new Uint32Array(1);

		//Modification des élements du
		//tableau par des nb aléatoires
		do cryptoObject.getRandomValues(x);
		while (x[0] - x[0] % maxRange > 4294967296 - maxRange);

		return x[0] % maxRange;
	} else {
		return 0;
	}
}

//Permet de générer un UUID de
//longueur souhaitée (ou 10 si pas de paramètre)
function generate_uuid(length){
	var length = length !== undefined ? length : 10;
	//Fallback repeat sur string
	//pour les anciens navigateurs
	if(!String.prototype.repeat){
		String.prototype.repeat = function(length){
			var length = parseInt(length);
			if (length < 1) return '';

			var result = '',
			pattern = this.valueOf();

			while (length > 1) {
				if(length & 1) result += pattern;
				length >>= 1, pattern += pattern;
			}
			return result + pattern;
		};
	}
	var mem = "0x1"+("0".repeat(length));
	return Math.floor((1 + Math.random()) * mem).toString(16).substring(1);
}

function readable_size(bytes) {
	var thresh = 1000;
	if(Math.abs(bytes) < thresh) {
		return bytes + ' B';
	}
	var units =  ['ko','Mo','Go','To','Po','Eo','Zo','Yo'];

	var u = -1;
	do {
		bytes /= thresh;
		++u;
	} while(Math.abs(bytes) >= thresh && u < units.length - 1);
	return bytes.toFixed(1)+' '+units[u];
}

/**
 * Permet de faire cligner l'onglet
 * navigateur avec un message custom
 * @param  {string} message     => le message à afficher
 * @param  {int} 	interval 	=> l'intervalle entre 2 clignotement en ms
 * @param  {int} 	repetitions => le nombre de clignotements
 */
function blink_tab(message, interval, repetitions) {
	interval = interval != undefined && !isNaN(interval) ? interval : 750;

	repetitions = parseInt(repetitions)*2;
	if(isNaN(repetitions)) repetitions = 10;
	if(repetitions%2!==0) repetitions += 1

	var original = document.title,
	    timeoutId,
	    blink = function() {
	    	document.title = document.title == message ? original : message;
	    	if(--repetitions > 0) timeoutId = setTimeout(blink, interval);
	    },
	    clear = function() {
	    	clearTimeout(timeoutId);
	    	document.title = original;
	    	window.onmousemove = null;
	    	timeoutId = null;
	    };

	if(!timeoutId) {
		timeoutId = setTimeout(blink, interval);
		window.onmousemove = clear;
	}
}

//Échappe les caractères spéciaux utilisés dans les regexps
function escape_regex_chars(text){
	//return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
	return text.replace(/[-[\]{}()*+!<=:?.\/\\^$|#\s,]/g, '\\$&');
}

//Détecte si le navigateur est un mobile ou non
function is_phone(){
  var navigatorName = navigator.userAgent||navigator.vendor||window.opera;
  	if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(navigatorName)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigatorName.substr(0,4)))
  		return true;
  	return false;
}

//Retourne le nom complet d'un jour en fonction de son numéro (1: Lundi,..., 7: Dimanche)
function day_name($day){
    $days = ['Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi','Dimanche'];
    //Pour gérer le cas du dimanche car Date().getDay() pour un dimanche retourne 0.
    $day = $day==0 ? 7 : $day;
    return $days[$day-1]!=null ? $days[$day-1] : $day;
}
//Retourne le nom complet d'un mois en fonction de son numéro
function month_name($month){
	$months = ['Janvier','Fevrier','Mars','Avril','Mai','Juin','Juillet','Aout','Septembre','Octobre','Novembre','Décembre'];
	return $months[$month]!=null ? $months[$month] : $month;
}
//Supprime la valeur ciblée d'un tableau
function remove_array_value(array, item){
	var index = array.indexOf(item);
	if(index !== -1) array.splice(index, 1);
}
//Gestion des lignes de table en striped avec rowspan
function manage_striped_rowspan(table){
	var i = 0;
	var cols = table.find("tbody tr:not(.hidden):first").children().length;
	if($("tbody tr:not(.hidden):first", table).find("[colspan]").attr("colspan")!=null)
	    cols += (parseInt($("tbody tr:not(.hidden):first").find("[colspan]").attr("colspan"))-1);

	$("tbody tr:not(.hidden)",table).each(function(){
		var tr = $(this);
		var child = tr.children().length;

		if(tr.find("[colspan]").attr("colspan")!=null)
			child += (parseInt(tr.find("[colspan]").attr("colspan"))-1);

		if(child>(cols-1)){
			if(i%2==0) tr.addClass("striped-row");
			i++;
		} else {
			tr.addClass(tr.prev().attr("class"));
		}
	});
}

/** PERMISSION **/
//Récuperation d'une liste de permission dans le tableau #permissions
function core_right_search(callback){
	var data = {
		action:'core_right_search',
		firm:$('#permission-firm').val(),
	};

	var modal = $('#permission-modal');
	modal.attr('data-firm',data.firm)
	data.uid = modal.attr('data-uid');
	data.scope = modal.attr('data-scope');

	$('#permissions tbody tr:visible').remove();

	$('#permissions').fill(data,function(response){
		if(callback!=null) callback();
	});
}

//Ajout ou modification d'élément permission
function core_right_edit(data){
	var options = $.extend({
		read : true,
		edit : true,
		delete : true,
		configure : true,
		recursive : true
	},data);



	var modal = $('#permission-modal');
	modal.find('.col-recursive,.col-configure,.col-read,.col-edit,.col-delete').addClass('hidden');

	if(options.firm === null){

		$('.permission-firm-block').removeClass('hidden');
	}else{
		$('#permission-firm').val(options.firm);
		$('.permission-firm-block').addClass('hidden');
	}

	if(options.recursive) modal.find('.col-recursive').removeClass('hidden');
	if(options.configure) modal.find('.col-configure').removeClass('hidden');
	if(options.read) modal.find('.col-read').removeClass('hidden');
	if(options.edit) modal.find('.col-edit').removeClass('hidden');
	if(options.delete) modal.find('.col-delete').removeClass('hidden');

	modal.attr('data-save',options.saveAction);
	modal.attr('data-delete',options.deleteAction);
	modal.attr('data-scope',data.scope).attr('data-uid',data.uid);




	var myFirm = $('#loginHeader').attr('data-firm');
	if(options.firm!==null) myFirm = options.firm;
	$.action({
		action: 'core_firm_search',
		export : false
	},function(response){
		var html = '<option value="">Tous</option>';
		for(var k in response.rows){
			var firm = response.rows[k];
			html+='<option '+(myFirm == firm.id ? "selected='selected'":"")+' value="'+firm.id+'">'+firm.label+'</option>';
		}
		$('#permission-firm').html(html);

		modal.modal('show');
		$('#permission-firm',modal).val();
		modal.unbind('shown.bs.modal').on('shown.bs.modal', function () {
		 	core_right_search();
		});
	});




}

//Ajout ou modification d'élément permission
function core_right_save(){
	var modal = $('#permission-modal');
	var data = $('#permission-form').toJson();
	data.action = modal.attr('data-save');
	data.uid = modal.attr('data-uid');
	data.scope = modal.attr('data-scope');
	data.firm = $('#permission-firm').val();

	var target = $('#target').data('values');
	if(target && target.length>0){
		target = target[0];
		data.targetScope = target.entity;
		data.targetUid = target.uid;
	}

	$.action(data,function(r){
		core_right_search();
		$('#permission-form').clear();
		init_components(modal);
	});
}


//Suppression d'élement permission
function core_right_delete(element){
	if(!confirm('Êtes-vous sûr de vouloir supprimer cet item ?')) return;
	var line = $(element).closest('tr');
	var modal = $('#permission-modal');

	$.action({
		action: modal.attr('data-delete'),
		id: line.attr('data-id')
	},function(r){
		line.remove();
		$.message('info','Item supprimé');
	});
}

// History
function core_history_search(callback){
	var panel = $('.history-panel');

	$('.comments-loader', panel).removeClass('hidden');
	$('.comments', panel).fill({
		action: 'core_history_search',
		keyword: $('.comment-keyword').val(),
		uid: panel.attr('data-uid'),
		scope: panel.attr('data-scope'),
	},function(){
		$('.comments-loader', panel).addClass('hidden');
		$('.comment[data-importance="important"] .history-importance input', panel).prop('checked',true);
		init_tooltips();
		if(callback!=null) callback();
	});
}

function history_add(element,data){
	var tpl = $('.comments >li:eq(0)').get(0).outerHTML;
	if(!data){
		var now = new Date();
		data = {
			type : {icon: 'far fa-comments', color:'#6ab04c', slug: 'comment'},
			created : {fullname: day_name(now.getDay())+' '+now.getDate()+' '+month_name(now.getMonth())+' '+now.getFullYear(), time: now.getHours()+':'+now.getMinutes()},
			creator : {fullname: 'Vous'},
			sort : ''
		};
	}
	var comment = $(Mustache.render(tpl,data)).removeClass('hidden');

	if(element){
		var commentAfter = $(element).closest('.comment');
		var sort = commentAfter.attr('data-sort') && !isNaN(commentAfter.attr('data-sort')) ? parseFloat(commentAfter.attr('data-sort')) : 0  ;
		comment.attr('data-replace-sort',sort);
	}else{
		var commentAfter = $('.history-panel .comments >li:eq(0)');
	}
	commentAfter.after(comment);
	history_edit(comment);
}


function history_edit(element){
	var comment = $(element);
	if(comment.attr('data-edition-mode') == "true" || comment.attr('data-type')!='comment' ) return;
	comment.attr('data-edition-mode','true');
	var commentElement = $('.history-content', comment);
	var content = commentElement.html();
	var textarea = $('<textarea data-simple="true" class="w-100" data-buttons="strong,em,underline,del,unorderedList,orderedList" data-type="wysiwyg" data-mention-user="user">'+content+'</textarea>');

	commentElement.html(textarea);
	init_components(commentElement);
	$('.trumbowyg-editor',commentElement).focus();
}

function core_history_save(element){
	var comment = $(element);
	var commentElement = $('.history-content', comment);

	comment.removeAttr('data-edition-mode');
	var message = comment.find('textarea').val();
	message = message == '' ? 'Aucun commentaire' : message;
	commentElement.html(message);
	var panel = $('.history-panel');
	var parameters = window.location.href.match(/[\\?&]([^&#]*)=([^&#]*)/g);
	var urlParameters = {};
	for (var key in parameters) {
		var couple = parameters[key].substring(1, parameters[key].length).split('=');
		urlParameters[couple[0]] = couple[1];
	}
	var replaceSort = isNaN(comment.attr('data-replace-sort')) ? null :  parseInt(comment.attr('data-replace-sort'));
	var importanceElement = comment.find('.history-importance input')
	var importance = importanceElement.prop('checked') ? 'important' : 'normal';

	$.action({
		action: 'core_history_save',
		id: comment.attr('data-id'),
		sort: comment.attr('data-sort'),
		replaceSort:replaceSort,
		scope : panel.attr('data-scope'),
		uid: panel.attr('data-uid'),
		comment : message,
		importance : importance,
		meta:urlParameters
	},function(r){
		if(replaceSort){
			$('.history-panel .comment:visible').each(function(){
				var element =  $(this);
				if(isNaN(element.attr('data-sort'))) return ;
				var sort =  parseInt(element.attr('data-sort'));
				if(sort<replaceSort) return;
				element.attr('data-sort',sort+1);
			});
		}
		comment.attr('data-sort',r.sort);
		comment.attr('data-id',r.id);
		importanceElement.attr('data-importance', importance);
	});
}

function core_history_importance_save(element){
	var importance = $(element).prop('checked') ? 'important' : 'normal';
	var comment = $(element).closest('.comment');
	var id = $(element).closest('.history-panel').attr('data-uid');
	$.action({
		action: 'core_history_importance_save',
		id: comment.attr('data-id'),
		importance : importance
	},function(r){
		comment.attr('data-importance', importance);
		core_history_importance_save_count(id);

	});
}

function core_history_delete(element){
	if(!confirm('Êtes-vous sûr de vouloir supprimer ce commentaire ?')) return;
	var comment = $(element).closest('.comment');
	var id = $(element).closest('.history-panel').attr('data-uid');
	$.action({
		action: 'core_history_delete',
		id: comment.attr('data-id')
	},function(r){
		comment.remove();
		core_history_importance_save_count(id);
	});
}

function core_history_importance_save_count(uid){
	var count = $('.history-importance input:checked').length;
	var historyNotification = $('a[data-uid="'+uid+'"] .history-notification');
	if(count == 0){
		historyNotification.addClass('hidden');
		return;
	}
	historyNotification.removeClass('hidden').html(count).attr('data-original-title',count+' messages importants');
}


/*
Convertit la chaine de caractères passées en paramètres en entités html
# htmlentities
*/
function html_entities(str){
	return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}

//Override base64 encode avec gestion chars unicode (encodés sur 2 bytes ou +)
//Compatible anciens navigateurs
function btoa_unicode(str) {
    //1. encodeURIComponent pour avoir la chaîne UTF-8 encodée avec les %,
    //2. On encode le résultat en bytes bruts
    //3. On envoie dans btoa
    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
        function toSolidBytes(match, p1) {
            return String.fromCharCode('0x' + p1);
    }));
}
//Override base64 decode avec gestion chars unicode (encodés sur 2 bytes ou +)
//Compatible anciens navigateurs
function atob_unicode(str) {
    //cf btoa_unicode() mais cheminement inverse
    return decodeURIComponent(atob(str).split('').map(function(c) {
        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
    }).join(''));
}
