/**
 * Auto Completion Class
 * @author 58062 Florian Collot
 * @copyright technomarine.com
 * var autoCompletion = new AcSLS(inputElement, urlToRequest, target, {
 * 		'delay': 200, (in millisecond),
 * 		'defaultValue' : '-1', (send if the input value is empty)
 * 		'result'	:	10, (nb result queried)
 * 		'method'	:	'post', (HTTP method used),
 * 		'caseSensitive'	: false,
 * 		'catchResult' 	: false,
 * 		'catchSelect	: false,
 * 		'classes'	:	{
 * 						'generic' : 'ac',
 * 						'normal'  : 'option',
 * 						'hover'	  : 'hover'
 * 							}
 * 		'fks'		: [{
 * 						'target' : 'tableName',
 * 						'value'	 : 'string' or element,
 * 						'column' : 'string'
 * 						}],
 * 		'gap'		: {
 * 						'top' 	: 0,
 * 						'left'	: 0,
 * 						'width'	: 0
 * 					},
 * 
 * 		onResult : function(xhr){} // Only available if catchResult = true
 * 		onSelect : function(element){} // Only available if catchSelect = true
 * 
 * 	});
 */

var AcSLS = new Class ({
	Implements: [Events, Options],
	options : {
		'delay' : 200,
		'defaultValue' : '-1',
		'results' : 10,
		'method' : 'post',
		'caseSensitive' : false,
		'catchResult' : false,
		'catchSelect' : false,
		'classes' : {
			'generic' : 'ac',
			'normal'  : 'option',
			'hover'	  : 'hover'
				},
		'fks' : [],
		'gap' : {
			'top' 	: 0,
			'left'	: 0,
			'width'	: 0
			}
	},
	initialize:function(element, url, target, options){
		this.setOptions(options);
		// Check Element Existing
		if (typeof(element) == 'string'){
			if ($chk($(element)))
				element = $(element);
		}		
		if (!$chk(element))
			return false;
		if (url == null || url == '')
			return false;
		if (target == null || target =='')
			return false;
		
		this.url = url;
		this.target = target;
		this.infos = {'id' : element.get('id'), 'name' : element.get('name')};
		if (AcSLS.elements[this.infos.id] != null)
			return false;
		
		if (this.options.method.toLowerCase() != 'post' && this.options.method.toLowerCase() != 'get')
			this.options.method = 'get';
		if (this.options.method == 'get')
			this.url = this.url.substr(0, this.url.lastIndexOf('.'));
		
		this.fired = null;
		this.hidden = null;
		this.element = element;
		this.overflow = null;
		this.crrentLabel = null;
		this.currentValue = {'user' : '', 'know': ''};
		this.currentHover = null;
		this.total = null;
		
		if (!$chk($(this.infos.id+"_hide_value"))){
			var hidden = new Element('input', {
				'type' : 'hidden',
				'name' : this.infos.name+"_hide_value",
				'id' : this.infos.id+"_hide_value",
				'styles' : {
					'display' : 'none'
				},
				'value' : this.options.defaultValue
			}).inject(element, 'after');
		}
		this.hidden = $(this.infos.id+"_hide_value");
		// Create AutoCompletion Block
		var div = new Element('div', {
			'class' : this.options.classes.generic+'_container',
			'id'	: this.options.classes.generic+'_container_'+this.infos.id
		});
		
		$$('body')[0].grab(div);
		this.overflow = $(this.options.classes.generic+'_container_'+this.infos.id);
		this.element.addEvent('keyup', function(){
			if (this.fired != null){
				$clear(this.fired);
			}
			this.fired = this.fireKeyUp.delay(this.options.delay, this);
		}.bind(this));
	},
	
	fireKeyUp : function(){
		var keywords = this.getKeywords();
		if (this.currentValue.user != null && keywords.main.trim() == this.currentValue.user.trim())
			return;
		if (keywords.main.trim() == ''){
			if (this.overflow.getStyle('display') == 'block')
				this.hideOverflow();
			this.currentValue.user = null;
			this.hidden.set('value', this.options.defaultValue);
			return;
		}
		
		if (this.currentValue.know.trim() != ''){
			if (keywords.main.trim() != this.currentValue.know.trim()){
				this.hidden.set('value', this.options.defaultValue);
				this.currentValue.know = '';
			}
		}
		
		this.currentValue.user = keywords.main;
		// Get FKS values
		var fkString = {'url' : '', 'param' : ''};
		if (this.options.fks.length > 0){
			var fks = {'columns':'','values':'','target':''};			
			for (var i=0;i<this.options.fks.length;i++){
				if (typeof(this.options.fks[i].value) == 'string')
					fks.values += (fks.values == '') ? this.options.fks[i].value : '||'+this.options.fks[i].value; 
				else
					fks.values += (fks.values == '') ? this.options.fks[i].value.get('value') : '||'+this.options.fks[i].value.get('value');

				fks.columns += (fks.columns == '') ? this.options.fks[i].column : '||'+this.options.fks[i].column;
				fks.target += (fks.target == '') ? this.options.fks[i].target : '||'+this.options.fks[i].target;
			}
			fkString.url = '/fk_targets/'+fks.target+'/fk_columns/'+fks.columns+'/fk_values/'+fks.values;
			fkString.param = '&fk_targets='+fks.target+'&fk_columns='+fks.columns+'&fk_values='+fks.values;
		}		
		var url = (this.options.method == 'get') ? this.url+'/keyword/'+keywords.main+'/target/'+this.target+'/nb/'+this.options.results+fkString.url+'.'+slsBuild.site.defaultExtension : this.url;
		var param = (this.options.method == 'get') ? null : 'keyword='+keywords.main+'&target='+this.target+'&nb='+this.options.results+fkString.param;
		
		if (this.currentRequest != null)
			this.currentRequest.cancel();
		
		this.currentRequest = new Request.JSON({
			'url' : (this.options.method == 'get') ? url : this.url,
			'method' : this.options.method,
			onComplete:function(xhr){
				this.currentRequest = null;
				this.overflow.empty();
				if (this.options.catchResult){
					this.fireEvent('result', [xhr]);
					return;
				}	
				if (typeof(xhr) == 'object' && xhr.length != 0){					
					var ul = new Element('ul', {
						'class' : this.options.classes.generic+'_ul'
					});
					
					ul.empty();
					
					var obj = this;
					for (var i=0;i<xhr.length;i++){
						if (xhr[i].value != '' && xhr[i].key != ''){
							var li = new Element('li').inject(ul);
							var span = new Element('span').inject(li);
							var a = new Element('a', {
								'title' : xhr[i].key,
								'href' : xhr[i].value,
								'html' : xhr[i].key
							}).inject(span);
							if (this.options.caseSensitive){
								if (xhr[i].key.trim() == keywords.main.trim()){
									this.hidden.set('value', xhr[i].value);
									this.currentValue.know = xhr[i].key;
								}
							}
							else {
								if (xhr[i].key.trim().toLowerCase() == keywords.main.trim().toLowerCase()){
									this.hidden.set('value', xhr[i].value);
									this.currentValue.know = xhr[i].key;
								}
							}
						}
					}
					if (ul.getFirst('li') != null){
						this.insertOptions(ul, 'li span a', xhr.length);
					}
				}
				else{
					if (this.overflow.getStyle('display') == 'block')
						this.hideOverflow();
				}
			}.bind(this)
		}).send(param);
	},
	
	insertOptions : function(element, clicks, total) {
		this.elementParent = element;
		this.itemSelector  = clicks;
		element.inject(this.overflow);
		var elClick = element.getElements(clicks);
		for (var i=0;i<elClick.length;i++){
			elClick[i].addEvent('mouseover', function(i){
				this.setCurrentHover(i);
			}.bind(this,[i]));
			elClick[i].addEvent('click', function(e){
				this.selectItem();
				e.stop();
			}.bind(this));
		}
		this.adjustOverflow();
		this.total = total;
		this.setCurrentHover(null);
		// Configure key Event
		if (this.overflow.getStyle('display') == 'none') {
			if (Browser.Engine.trident){
				$$('body')[0].addEvent('keydown', function(e){
					this.handleKey(e);
				}.bind(this));
				$$('body')[0].addEvent('click', function(e){
					this.handleClick(e);
				}.bind(this));
			}
			else{
				window.addEvent('keydown', function(e){
					this.handleKey(e);
				}.bind(this));
				window.addEvent('click', function(e){
					this.handleClick(e);
				}.bind(this));
			}
		}
		this.overflow.setStyle('display', 'block');
	},
	
	getKeywords : function(){
		var keywords = {
				'main' : this.element.get('value')
		};
		return keywords;
	},
	
	adjustOverflow : function(){
		var top = Display.getY(this.element)+parseInt(this.options.gap.top)+parseInt(this.element.getStyle('height').split("px")[0]);
		var left = Display.getX(this.element)+parseInt(this.options.gap.left);
		var width = parseInt(this.element.getStyle('width').split('px')[0])+parseInt(this.options.gap.width);
		this.overflow.setStyles({
			'top' : top.toString()+"px",
			'left': left.toString()+"px",
			'width' : width.toString()+"px"
		});
	},
	setCurrentHover : function(index){
		if (index == null)
			index = -1;
		var normal = this.options.classes.normal;
		var hover  = this.options.classes.hover;
		$$('#'+this.options.classes.generic+'_container_'+this.infos.id+' '+this.itemSelector).each(function(element, i){
			if (index == i){
				element.set('class', hover);
			}
			else
				element.set('class', normal);
			
		});
		this.currentHover = (index == -1) ? null : index;
	},
	selectItem : function() {
		if ($chk($$('#'+this.options.classes.generic+'_container_'+this.infos.id+' '+this.itemSelector)[this.currentHover])){
			if (this.options.catchSelect){
				this.fireEvent('select', [$$('#'+this.options.classes.generic+'_container_'+this.infos.id+' '+this.itemSelector)[this.currentHover]]);
				return;
			}
			var itemToSelect  = $$('#'+this.options.classes.generic+'_container_'+this.infos.id+' '+this.itemSelector)[this.currentHover];
			this.element.set('value', itemToSelect.get('text'));
			this.setHidden(itemToSelect.get('href'));
			this.currentValue.user = itemToSelect.get('text');
			this.currentValue.know = itemToSelect.get('text');
			this.hideOverflow();
		}
	},
	
	setHidden : function(value){
		this.hidden.set('value', value);
	},
	
	getHidden : function(){
		return this.hidden.get('value');
	},
	
	hideOverflow : function(){
		this.currentHover = null;
		if (Browser.Engine.trident){
			$$('body')[0].removeEvents('keydown');
			$$('body')[0].removeEvents('click');
		}
		else{
			window.removeEvents('keydown');
			window.removeEvents('click');
		}

		this.overflow.setStyle('display', 'none');
	},
	handleKey : function(e){
		/* Down = 40
		 * Up = 38
		 * Right = 39
		 * Left = 37
		 * Enter = 13
		 * Esc = 27 	
		 * Tab = 9
		 * Shift = 16
		 * Space = 32 
		 */
		if (e.code == 27 || e.code == 9)
			this.hideOverflow();
		if (e.code == 40){
			this.setNextHover();
			e.stop();
		}
		if (e.code == 38){
			this.setPreviousSelectHover();
			e.stop();
		}
		if (e.code == 13 || e.code == 39) {
			if (this.currentHover != null)
				this.selectItem();
			e.stop();
		}

	},
	handleClick : function(e) {
		if (navigator.appName == "Netscape")
		{document.captureEvents(Event.CLICK);}
		if (navigator.appName == "Microsoft Internet Explorer")
		{sX = event.clientX; sY = event.clientY;}
		else {sX = e.pageX;sY = e.pageY;}
		if (this.overflow.getStyle('display') == 'block')
		{
			var xMinOverflow = Display.getX(this.overflow);
			var yMinOverflow = Display.getY(this.overflow);
			var xMaxOverflow = xMinOverflow+parseInt(this.overflow.getStyle('width').split('px')[0]);
			var yMaxOverflow = yMinOverflow+parseInt(this.overflow.getStyle('height').split('px')[0]);
			if (sX > xMinOverflow && sX < xMaxOverflow && sY > yMinOverflow && sY < yMaxOverflow)
				return;
			else
				this.hideOverflow();
		}
		
	},
	setNextHover : function(){
		if (this.currentHover == null){
			var next = 0;
		}
		else{
			if ((parseInt(this.currentHover+1)) != parseInt(this.total)){
				var next = parseInt(this.currentHover)+1;
			}
			else
				var next = 0;
		}
		this.setCurrentHover(next);
	},
	setPreviousSelectHover : function (){
		if (this.currentHover == null){
			var prev = parseInt(this.total)-1;
		}
		else{
			if (parseInt(this.currentHover) != 0){
				var prev = parseInt(this.currentHover)-1;
			}
			else
				var prev = parseInt(this.total)-1;
		}
		this.setCurrentHover(prev);
	}
});
AcSLS.elements = {};

