/*
	1egal2 - Arkothèque
	Module d'autocomplétion
*/
;(function($,window,undefined){
	"use strict";
	var defaults = {
			'nbCharMin': 3
			,'url': ''
			,'useId': true
			,'nomParam': 'q'
			,'msDelay': 300
			,'champ': ''
            ,'showListOnFocus': false
			,'item_class': 'auto_item'
			,'list_class' : 'auto_list'
			,'useBlink' : true
			,'blink_class': 'auto_blink'
			,'useCache':true
			,'onSelect': false
	}, document = window.document;
	function ArkAutocomplete(element,options) {
		this.element = element;
		this.options = $.extend( {}, defaults, options) ; 
		this.cacheValue = ""; // valeur courante du champ
		this.list = [];
		this.$elemList = false;
		this.$elemChampId = false;
		this.init();
		this.updlCache = null;
		this.debug = {};
		this.debug.cacheCall =0;
	}
	ArkAutocomplete.prototype.init = function(){
		var self = this;
		var $elem = $(self.element);
		self.cacheValue = $elem.val();
		if(!!$elem.attr('data-char-min')) {
			self.options.nbCharMin = parseInt($elem.attr('data-char-min'));
		}
		
		self.options.champ = $elem.attr('name');
		$elem.attr('autocomplete','off');
		if(!!self.options.useId) {
			if($("#id_"+$elem.attr('name'),$elem.parent()).length>0) {
				self.$elemChampId = $("#id_"+$elem.attr('name'),$elem.parent());
			}
		}
		$elem.on('keyup',function(){
			if($(this).val()!=self.cacheValue) {
				// si différence (donc pas tab, alt ou entrée..)
				(!!self.$elemChampId)&&self.$elemChampId.val('');
				self.cacheValue = $(this).val();
				self.createList();
				self.delayUpdateVal();
			}
		});
        if (!!self.options.showListOnFocus) {
            $elem.on('focus',function(){
                self.createList();
                self.delayUpdateVal();
            });
        }
		$elem.on('blur',function(){
			// effacer la fenêtre d'autocomplete
			self.hideList();
		});
		$elem.on('ArkAutocompleteEndLoading',function(){
			self.loadingDiv('stop');
		}).on('ArkAutocompleteLoading',function(){
			self.loadingDiv('show');
		});
		
	};
	// lance l'update si le msDelay est passé
	ArkAutocomplete.prototype.delayUpdateVal = function delUpVal(){
		var self = this;
		if(!!delUpVal.to) clearTimeout(delUpVal.to);
		delUpVal.to = setTimeout(function(){
			self.updateList();
		},self.options.msDelay);
	};
	// lance l'update si le nb de caractères est >= à nbCharMin
	// memoize si l'option est active
	ArkAutocomplete.prototype.updateList = function updl(){
		var self = this;
		var $elem = $(self.element);
		if(!self.updlCache) self.updlCache = {}; // memoize
		if(self.cacheValue.length>=self.options.nbCharMin) {
			$elem.addClass('loading');
			$elem.trigger('ArkAutocompleteLoading');
			var url = self.options.url;
			var rdata = {};
			rdata[self.options.nomParam] = self.cacheValue;
			
			rdata['champ'] = self.options.champ;
			var callServer = true;
			if(!!self.options.useCache) {
				if(!!self.updlCache[self.cacheValue]) {
					self.list = self.updlCache[self.cacheValue];
					self.debug.cacheCall++;
					$elem.trigger('ArkAutocompleteEndLoading');
					self.createList();
					$elem.removeClass('loading');
					callServer = false;
				}
			}
			if(callServer) {
				var retourCallback = function(data){
					self.list = data;
					if(!!self.options.useCache) {
						self.updlCache[self.cacheValue] = data;
					}
					$elem.trigger('ArkAutocompleteEndLoading');
					self.createList();
					$elem.removeClass('loading');
				};
				if (typeof url === "function") {
					url.call(this, rdata, retourCallback);
				} else {
					$.getJSON(url,rdata, retourCallback);
				}
			}
		}
	};
	ArkAutocomplete.prototype.createList = function(){
		var self = this;
		var $elem = $(self.element);
		var items = [];
		if(self.list.length>0) {
			$.each(self.list,function(k,v){
				if(v.id!="more") {
					var pattern = self.cacheValue;
					pattern = pattern.replace(/[aàâ]/gi,'[aàâ]');
					pattern = pattern.replace(/[eèéê]/gi,'[eèéê]');
					pattern = pattern.replace(/[oô]/gi,'[oô]');
					pattern = pattern.replace(/[iîï]/gi,'[iîï]');
					pattern = pattern.replace(/[cç]/gi,'[cç]');
					pattern = pattern.replace("(", "\\(");
					pattern = pattern.replace(")", "\\)");
					var re = new RegExp("("+pattern+")","gi"); 
					if(self.options.truncate == "commence_par") {
						re = new RegExp("^("+pattern+")","gi"); 
					}
					var highlight = v.valeur.replace(re,'<strong>$1</strong>');
					if(typeof(v.valeurSupp)==='undefined') v.valeurSupp = "";
					items.push("<a href='Javascript:;' class='"+self.options.item_class+"' data-id='"+v.id+"'><span class='valeur'>"+highlight+"</span>&nbsp;<span class='valeur_supp'>"+v.valeurSupp+"</span></a>");
				}
				else {
					items.push("<span>"+v.valeur+"</span>");
				}
			});
			if(!!self.$elemList) {
				if(self.$elemList.hasClass('hidden')) self.$elemList.removeClass('hidden').fadeIn(400);
				self.$elemList.empty().html(items.join('')).css({
					'position':'absolute'
					,'top':($elem.offset().top+$elem.outerHeight()-1)
					,'left':$elem.offset().left
					,'width':($elem.outerWidth()-3)
				});
				self.$elemList.find('.'+self.options.item_class).off('click').on('click',function(){
					
					self.selectItem(this);
				});
			}
			else {
				var listHtml = "<div style='display:none;' class='"+self.options.list_class+"'>"+items.join('')+"</div>";
				var $list = $(listHtml);
				self.$elemList = $list;
				$elem.parent().append($list);
				$list.css({
					'position':'absolute'
					,'top':($elem.offset().top+$elem.outerHeight()-1)
					,'left':$elem.offset().left
					,'width':($elem.outerWidth()-3)
				});
					
				$list.find('.'+self.options.item_class).on('click',function(){
					self.selectItem(this);
				});
				$list.slideDown(300);
			}
		}
		else {
			self.hideList();
		}
	};
	ArkAutocomplete.prototype.hideList = function hideL(){
		var self = this;
		if(!!hideL.to) clearTimeout(hideL.to);
		if(!!self.$elemList) {
			hideL.to = setTimeout(function() {
				self.$elemList.addClass('hidden').slideUp(300);
			},200);
		}
	};
	ArkAutocomplete.prototype.selectItem = function(item){
		var self = this;
		var $elem = $(self.element);
		var $item = $(item);
		var valText = undefined;
		var valId = undefined;
		valText = $item.find('.valeur').text()
		$elem.val(valText);
		if(!!self.options.useId) {
			valId = $item.attr('data-id');
			self.$elemChampId.val(valId);
		}
		if (typeof self.options.onSelect === "function") {
			self.options.onSelect.call(self.element, [ valText, valId]);
		}
	};
	ArkAutocomplete.prototype.loadingDiv = function lddiv(action) {
		var self = this;
		if(!!self.options.useBlink) {
			var blinkMs = 500;
			var $elem = $(self.element);
			if(!self.$blinkElem) {
				self.$blinkElem = $('<span class="'+self.options.blink_class+'" style="display:none;"><span>load</span></span>');
				$elem.parent().append(self.$blinkElem);
			}
			if(action=='show') {
				self.$blinkElem.fadeIn(blinkMs);
				lddiv.to = setTimeout(function(){
					//
					self.loadingDiv('hide');
				},blinkMs);
				
			}
			else if(action=='hide'){
				self.$blinkElem.fadeOut(blinkMs);
				lddiv.to = setTimeout(function(){
					self.loadingDiv('show');
				},blinkMs);
			}
			else if(action='stop'){
				if(!!lddiv.to) clearTimeout(lddiv.to);
				self.$blinkElem.stop().fadeOut({
					duration:blinkMs
					,queue: false
				}).remove();
				self.$blinkElem = false;
			}
		}
	};
	$.fn.ArkAutocomplete = function(options) {
		var tempArgs = arguments;
		return this.each(function(){
			var $that = $(this);
			if(typeof($(this).data('ArkAutocomplete'))==='undefined') $(this).data('ArkAutocomplete',false);
			if($(this).data('ArkAutocomplete')===false) {
				// init
				$(this).data('ArkAutocomplete',new ArkAutocomplete($that,options));
			}
			else {
				var objectRef = $(this).data('ArkAutocomplete');
                if (typeof objectRef[ tempArgs[0] ] === "function") {
    				return objectRef[tempArgs[0]].apply(objectRef,Array.prototype.slice.call(tempArgs,1));
                } else {
                    console.log('erreur', objectRef, tempArgs);
                }
			}
		});

	};
})(jQuery,window);