/*
	Written by Yannick Van Avermaet
		
	All rights reserved © 2011
*/
	
cAutocompleter = Class.create({
	initialize: function(element, functions, options){
		this.element = $(element);
		this.functions = functions;
		this.options = options || {};
		
		this._setVariables();
		this._createElements();
		this._initEventHandlers();
		
		this.element.remove(); // remove the original element
	},
	
	_setVariables: function(){
		this.inputs = this.options.input || {};
		this.div = this.options.div || {};
		this.autocomp = this.options.autocomp || {};
		this.highlightClassName = 'selected';
		this.previous = null;
		this.selectFirstOnLoad = this.options.selectFirstOnLoad || false;
		this.addTypedToList = this.options.addTypedToList || false;
		this.dataArray = null;
		this.selectedElm = null;
		this.choicesOpen = false;
	},
	
	_createElements: function(){
		this._createChoicesElement();
		this._createInputElement();
	},
	
	_initEventHandlers: function(){
		Event.observe(this.input,'blur',this.doSomething.bind(this));
		Event.observe(this.input,'focus',this.doSomething.bind(this));
		Event.observe(this.input,'keydown',this.doSomething.bind(this));
	},
	
	_createChoicesElement: function(){
		this.choices = new Element('div', {'id' : this.div.id, 'className' : this.div.className}).hide();
		
		// IE FIX!
		if(Prototype.Browser.IE)
			this.choices.addClassName(this.div.className);
			
		this._insertElement(this.choices, this.element);
	},
	
	_createInputElement: function(){
		var inputValue = this.inputs.value ? this.inputs.value : this.inputs.standard ? this.inputs.standard : '';
		this.input = new Element('input', {'id' : this.inputs.id, 'className' : this.inputs.className, 'value' : inputValue});
		this.input.setAttribute('autocomplete', 'off');
		
		// Quick IE9 fix...
		this.input.name = this.inputs.name;
		this.input.value = inputValue;
		
		// IE FIX!
		if(Prototype.Browser.IE)
			this.input.addClassName(this.inputs.className);

		this._insertElement(this.input, this.element);
	},
	
	_insertElement: function(div, after){
		$(after).insert({
			'after' : div
		});
	},
	
	doSomething: function(event){
		switch(event.type){
			case 'blur':
				setTimeout(
					function(){
						if(this.input.value != ''){
							if(typeof this.functions.verifyData === 'function'){
								if(!this.functions.verifyData(this.input.value)){
									if(typeof this.functions.onFailed === 'function'){
										this.functions.onFailed();	
									}
								}
							}
						}
						if(this.input.value == '' && typeof this.functions.resetAC === 'function'){
							this.functions.resetAC();
						} 
						this._closeChoices();
					}.bind(this), 100);
				break;
			case 'focus':		
				this.input.value = (this.input.value != this.inputs.standard) ? this.input.value : '';
				break;
			case 'keydown':
				switch(event.keyCode){
					case 8:
						setTimeout(function(){
							if(this.input.value.length < (this.autocomp.minChars || 2))
								this._closeChoices();
							else
								this.retrieveData();	
							
						}.bind(this), 0);
						break;
					case Event.KEY_RETURN:
						this._handleSelect(this.previous, event);
						break;
					case Event.KEY_TAB:
						this._handleSelect(this.previous, event);
						break;
					case Event.KEY_ESC:
						this.selectedElm = null;
						this._closeChoices();
						break;
					case Event.KEY_UP:
						this.selectedElm = null;
						if(this.choicesOpen) this._handlePrevious();
						break;
					case Event.KEY_DOWN:
						this.selectedElm = null;
							if(this.choicesOpen) this._handleNext();
						break;
					default:
						this.selectedElm = null;
						this.retrieveData();
						break;
				}
				break;
		}
	},
	
	_handlePrevious: function(){
		var prevElm = null;
		if(this.previous != null){
			prevElm = this.previous.previous();
			if(prevElm == null)
				prevElm = this.choices.down('ul').select('li:last-child')[0];
		}
		else{
			prevElm = this.choices.down('ul').select('li:last-child')[0];
		}
		
		if(prevElm !== null){
			if(this.previous != null)
				this.previous.removeClassName(this.highlightClassName);
			this.previous = prevElm;
			if(this.previous.hasClassName('noselect')){
				this._handlePrevious();
			}
			else{
				this.previous.addClassName(this.highlightClassName);
				this.previous.scrollIntoView(false);
			}
		}
	},
	
	_handleNext: function(){
		var nextElm = null;
		if(this.previous != null){
			nextElm = this.previous.next();
			if(nextElm == null)
				nextElm = this.choices.down('ul').down('li');
		}
		else{
			nextElm = this.choices.down('ul').down('li');
		}
		
		if(nextElm !== null){
			if(this.previous != null)
				this.previous.removeClassName(this.highlightClassName);
			this.previous = nextElm;
			if(this.previous.hasClassName('noselect')){
				this._handleNext();
			}
			else{
				this.previous.addClassName(this.highlightClassName);
				this.previous.scrollIntoView(false);
			}
		}
	},
	
	retrieveData: function(){
		setTimeout(function(){
			if((this.input.value.length) >= (this.autocomp.minChars || 2)){				
				var firstLetter = this.input.value.substring(0,1).toLowerCase();
				
				var firstLetterRegEx = /^[a-z-0-9]$/;
				if(!firstLetterRegEx.test(firstLetter))
					firstLetter = 'special';
				
				if(window['cities_'+firstLetter])
					this.dataArray = eval('cities_'+firstLetter);
				else
					this._closeChoices();	
				
				this.showData();
			}
		}.bind(this),0);
	},
	
	showData: function(){
		var length = this.dataArray.length;
		var highlightRegex = new RegExp('('+this.input.value.replace(/^\s+/,'').replace(/\s+$/,'')+')', "i");
		
		var i;
		var hits = new Array();
		var isNumber = !isNaN(this.input.value);
		for(i = 0; i < length; i++){
			var elm = this.dataArray[i];
			var city = elm[0];
			var postalCode = elm[1];
			
			if(city.toLowerCase().indexOf(this.input.value.toLowerCase()) == 0 || (isNumber && (postalCode.toString().indexOf(this.input.value) == 0 || postalCode.toString().indexOf('-'+this.input.value) > 0))){
				var tmpPostalCode = postalCode;
				if(postalCode.toString().indexOf('-') > 0)
					tmpPostalCode = postalCode.substring(0,4);
				hits.push('<li id="'+tmpPostalCode+'">'+city.replace(highlightRegex, '<b>$1</b>')+'</li>');
			}
		}
		
		if(hits.length > 0){
			hits.sort(function(a, b){
				var regexStripHtml = /<(?:.|\s)*?>/g;
				
				var A = a.toLowerCase().replace(regexStripHtml, '');
				var B = b.toLowerCase().replace(regexStripHtml, '');
				if (A < B){
					return -1;
				}
				else if (A > B){
					return  1;
				}
				else{
					return 0;
				}
			});
			
			if(this.selectFirstOnLoad){
				var firstElm = hits[0];
				hits[0] = firstElm.substring(0,3) + ' class="'+this.highlightClassName+'"' + firstElm.substring(3);
			}
			
			this.choices.innerHTML = '<ul>' + hits.join('') + '</ul>';
			
			// Update width of this.choices	
			var elmOffset = this._elmOffset(this.input);
			
			this.choices.setStyle({
				position: 'absolute',
				top: (parseInt(elmOffset.top)+parseInt(this.input.getHeight()))+'px',
				left: parseInt(elmOffset.left)+'px',
				width: this.input.getWidth()+'px'
			});
			
			if(this.selectFirstOnLoad)
				this.previous = this.choices.down('ul').down('li'); // the first element is selected
			
			this._showChoices();
			Event.observe(this.choices.down('ul'),'mouseover',this.highlight.bind(this));
			Event.observe(this.choices.down('ul'),'click',this.selectLi.bind(this));
		}
		else{
			this.choices.innerHTML = '';
		}
	},
	
	selectLi: function(event){
		var elm =  Event.findElement(event, 'LI');
		this._handleSelect(elm, event);
	},
	
	_handleSelect: function(elm, event){
		if(elm != null && this.selectedElm == null){
			this.selectedElm = elm;
			var regex = /\s<span.*>\(\d*\)<\/span>/gi;
			var regex2 = /<span.*>.*<\/span>/gi; // custom edit
			var regex3 = /<b>(.*)<\/b>/gi; // custom edit
			var text = elm.innerHTML.replace(regex,'').replace(regex2,'').replace(regex3, '$1');
			this.input.value = text;
			
			var obj = elm;
			obj.setAttribute('setValue', text);
			
			if(typeof this.functions.onSuccess === 'function')
				this.functions.onSuccess(obj);
			
			Event.stop(event);
			this._closeChoices();
			
			this.input.focus();
		}
	},
	
	_showChoices: function(){
		this.choicesOpen = true;
		if(typeof(Effect) !== 'undefined')
			Effect.Appear(this.choices,{duration:0.15});
		else
			this.choices.show();
	},
	
	_closeChoices: function(){
		this.choicesOpen = false;
		if(typeof(Effect) !== 'undefined')
			Effect.Fade(this.choices,{duration:0.15});
		else
			this.choices.hide();
	},
	
	highlight: function(event){
		var elm =  Event.findElement(event, 'LI');
		
		if(elm != null && !elm.hasClassName(this.highlightClassName) && !elm.hasClassName('noselect')){	
			elm = $(elm);
			
			if(this.previous != null)
				this.previous.removeClassName(this.highlightClassName);
			
			elm.addClassName(this.highlightClassName);
			this.previous = elm;
		}
	},
	
	_elmOffset: function(elm){
		//if(Prototype.Version.substring(0,3) === '1.7')
		//	return {top: elm.measure('top'), left: elm.measure('left')};
			
		return elm.cumulativeOffset();
	}
})
