auto_completes = {};

lang.autocomp = {
	'es':{},
	'en':{}
};

AutoCompleteComponent = Class.create();
AutoCompleteComponent.prototype = {
	
	initialize: function(id, options) {
		this.id = id;
		this.wrapper = $(this.id+'_wrapper');
		this.option_list = $(this.id+'_option_list');
		this.sug_wrapper = $(this.id+'_suggestion_wrapper');
		this.input = $(this.id+'_input');
		if ($(this.id+'_input_value')) this.input_value = $(this.id+'_input_value');
		
		this.setOptions(options);
		
		if (this.options.lister) {
			this.add_btn = $(this.id+'_add_btn');	
		}
		
		updaters[this.id+'_update'] = new Updater(this.id + '_update', '', '', {parent:this});	
		this.updater = updaters[this.id+'_update'];
		
		this.suggested_options = [];
		this.cur_options = [];
		this.last_value = '';
		
		this.injectBehaviours();
		
	},
	
	setOptions: function(options) {
		this.options = {regExAny:'',
						regExFlags:''
						}.extend(options);
	},
	
	injectBehaviours: function() {
		
		if (this.add_btn) {
			this.add_btn.onclick = this.addToListerHandler.bindAsEventListener(this);	
			this.add_btn.onmouseover = this.overHandler.bindAsEventListener(this);	
			this.add_btn.onmouseout = this.outHandler.bindAsEventListener(this);	
			var dims_btn = Element.getDimensions(this.add_btn.id);
			//if (console) console.log('BTN_DIMS: '+dims_btn.width+'x'+dims_btn.height);
			Element.show(this.add_btn.id);
		}	

		if (this.add_btn) {
			//this.input.style.width = (dims_input.width - dims_btn.width - 10) + 'px';
		}
		
		this.input.onkeyup = this.getOptions.bindAsEventListener(this);
		this.input.onfocus = this.focusHandler.bindAsEventListener(this);
		this.input.onblur = this.blurHandler.bindAsEventListener(this);
		
		if (this.options.filter) {
			Element.addClassName(this.input.id, this.options.filter.className);
			this.input.value = this.options.filter.msg;
		}
		
		var dims_input = Element.getDimensions(this.input.id);
		//if (console) console.log('AC_INPUT_DIMS: '+dims_input.width+'x'+dims_input.height);
		if (this.options.wrapper_pos) {
			this.sug_wrapper.style.left = this.options.wrapper_pos.x+'px';	
			this.sug_wrapper.style.top = this.options.wrapper_pos.y+'px';
			if (this.options.wrapper_pos.width) {
				this.sug_wrapper.style.width = this.options.wrapper_pos.width+'px';
			}
		}
		
	},
	
	overHandler: function(e) {
		var src = e.srcElement ? e.srcElement : e.target;
		src.style.cursor = 'pointer';
	},
	
	outHandler: function(e) {
		var src = e.srcElement ? e.srcElement : e.target;
		src.style.cursor = '';
	},
	
	focusHandler: function(e) {
		this.is_active = true;
		if (this.cur_options.length > 0) {
			Element.show(this.sug_wrapper.id);
		}
		if (this.options.filter) {
			ApexUtil.defaultText('focus', this.input.id, this.options.filter.msg, this.options.filter.className);
		}
	},
	
	blurHandler: function(e) {
		this.is_active = false;
		if (!this.options.no_hide) Element.hide(this.sug_wrapper.id);
		if (this.options.filter) {
			ApexUtil.defaultText('blur', this.input.id, this.options.filter.msg, this.options.filter.className);
		}
	},
	
	addToListerHandler: function(e) {
		if (this.cur_selected_op) {
			listers[this.options.lister].addOption([this.cur_selected_op.label, this.cur_selected_op.id]);
		} else if(this.options.allow_empty) {
			var value = (this.options.label_as_value) ? this.input.value : -1;
			listers[this.options.lister].addOption([this.input.value, value]);
		}
		this.reset();
	},
	
	reset: function() {
		this.suggestions = [];
		this.cur_options = [];
		this.last_value = '';
		this.input.value = '';
		this.input.focus();
		Element.hide(this.sug_wrapper.id);
		this.onReset();
	},
	
	onReset: function() {},
	
	
	getOptions: function(e) {
				
		var target_str = this.input.value;
		
		//if (console) console.log('calling getOptions ['+target_str+']');
		
		if (target_str.length == 0) {
			//if (console) console.log('TARGET STR LENGTH: '+target_str.length);
			this.reset();
			return false;
		}
		
		if (target_str) {
		
			var key = e.which || -1;
		
			if (key == 13) { // return
				if (!this.cur_selected_op) {
					if (target_str && this.cur_options.length == 0) {
						this.addToListerHandler();
					} else {
						this.selectOption(0);	
					}
				} else {
					if (target_str == this.cur_selected_op.label && this.options.lister) {
						this.addToListerHandler();
					} else {
						this.selectOption(this.cur_selected_op.index);	
					}
				}
			} else if(key == 38) { // up
				if (this.cur_options.length > 0) {
					Element.show(this.sug_wrapper.id);
					this.prevOption();
				}
				
			} else if(key == 40) { // down
				if (this.cur_options.length > 0) {
					Element.show(this.sug_wrapper.id);	
					this.nextOption();
				}
			} else if (target_str != this.last_value) {
			
				//if (console) console.log('INDEX of ['+this.last_value+'] IN ['+target_str+'] = '+target_str.indexOf(this.last_value));
				if (target_str[0] != this.last_value[0] ||  
					(this.suggested_options.length == 0 && this.no_results && target_str.length < 3) ||
					this.last_value.length > target_str.length ||
					(!this.last_value)) {
					this.last_value = target_str;
					var callParams = this.options.args || [];
					callParams.push('ref='+this.options.ref);
					callParams.push('json=1');
					callParams.push('args[q]='+target_str);
					this.updater.callService('system.autoComplete', callParams);
					
				} else {
					this.last_value = target_str;
					this.filterOptions(target_str);	
				}
			
			}
				
		} 
		
	},
	
	onFill: function(ob) {
		var service = this.options.onFill[0];
		var callParams = this.options.onFill[1] || [];
		if (service) {
			callParams.push('id='+ob.id);
			this.updater.callService(service, 	callParams);
		}
	},
	
	ajaxUpdate: function(ajaxResponse) {
		
		this.updater.update(ajaxResponse);
		
		var optionsTag = ajaxResponse.getElementsByTagName('options')[0];
		if (optionsTag) {
			if (optionsTag.getAttribute('count') > 0) {
				this.suggested_options = eval(RicoUtil.getContentAsString(optionsTag));
				this.cur_options = [];
				this.filterOptions(this.last_value);
			} 
		}
		
	},
	
	filterOptions: function(target) {
		this.cur_options = this.makeMatches(target);
		this.buildList();
		if (this.cur_options.length > 0) {
			if (!Element.visible(this.sug_wrapper.id)) {
				if (this.options.animate) {
					var effect = new Effect.BlindDown(this.sug_wrapper.id, {duration: 1});
				} else {
					Element.show(this.sug_wrapper.id);
				}
			}
		} else {
			if (!this.options.no_hide) Element.hide(this.sug_wrapper.id);
		}
	},
	
	makeMatches: function(compareStr) {
		//if (console) console.log('MATCH STRING: '+compareStr+ ' with RegEx '+this.options.regExAny+compareStr);
		var ops = (this.cur_options.length > 0) ? this.cur_options : this.suggested_options;
		var matchArray = [];
		var regExp = new RegExp(this.options.regExAny+compareStr, this.options.regExFlags);
		for(var i=0; i<ops.length; ++i) {
			//if (console) console.log('MATCHING TO: '+ops[i].label);
			var the_match = ops[i].label.match(regExp);
			if (the_match) {
				matchArray.push(ops[i]);	
			}
		}
		return matchArray;
	},
	
	buildList: function() {
		
		this.option_list.innerHTML = '';
		
		for(var i=0; i<this.cur_options.length; i++) {
			//if (console) console.log('CREATING LI: '+this.cur_options[i].label);
			var li = document.createElement('li');
			li.id = this.id+'_auto_'+i;
			li.className = "clearfix";
			if (i % 2 == 0) li.className += " dark";
			if (i == 0) li.className += " selected";
			var a = document.createElement('a');
			a.href = "javascript:auto_completes['"+this.id+"'].selectOption("+i+");"; 
			// "javascript:auto_completes['"+this.id+"'].selectOption("+i+");";
			a.setAttribute('onfocus', "this.blur();");
			a.appendChild(document.createTextNode(this.cur_options[i].label));
			li.appendChild(a);
			//a.onclick = this.selectOption.bind(this, i);
			a.onfocus = this.focusHandler.bindAsEventListener(this);
			this.option_list.appendChild(li);
			
			this.cur_options[i].index = i;
		}
		//if (console) console.log('OPTION LIST: '+this.option_list.innerHTML);
		
		this.cur_selected_op = this.cur_options[0];
	
	},
	
	setValue: function(label, value) {
		Element.removeClassName(this.input.id, this.options.filter.className);
		this.input.value = label;
		if (this.input_value) {
			this.input_value.value = value;	
		}
	},
	
	selectOption: function(index) {
		this.input.focus();
		
		this.input.value = this.cur_options[index].label;
		
		if (this.cur_selected_op) {
			Element.removeClassName(this.id+'_auto_'+this.cur_selected_op.index, 'selected');
		}
		
		this.cur_selected_op = this.cur_options[index];
		Element.hide(this.sug_wrapper.id);
		Element.addClassName(this.id+'_auto_'+index, 'selected');
		
		if (this.input_value) {
			this.input_value.value = this.cur_selected_op.id;	
			//if (console) console.log('SETTING OPTION TO '+index+' WITH VALUE '+this.input_value.value);
		}
		
		if (this.options.onFill) {
			this.onFill(this.cur_selected_op);	
		}
		this.onSelect(this.cur_selected_op);
	
	},
	
	onSelect: function() {},
	
	nextOption: function() {
		var cur_index = (this.cur_selected_op) ? this.cur_selected_op.index : 0;
		Element.removeClassName(this.id+'_auto_'+cur_index, 'selected');
		
		cur_index++;
		if (cur_index >= this.cur_options.length) cur_index = 0;
		
		this.cur_selected_op = this.cur_options[cur_index];
		Element.addClassName(this.id+'_auto_'+cur_index, 'selected');
	},
	
	prevOption: function() {
		var cur_index = (this.cur_selected_op) ? this.cur_selected_op.index : 0;
		Element.removeClassName(this.id+'_auto_'+cur_index, 'selected');
		
		cur_index--;
		if (cur_index < 0) cur_index = this.cur_options.length -1;
		
		this.cur_selected_op = this.cur_options[cur_index];
		Element.addClassName(this.id+'_auto_'+cur_index, 'selected');
	}

	
};
