/*
 * Carlos Hernandez carlos.hernandez@turner.com
 * requires prototype
 * requires jObject
 */
var KEY_ENTER		= 13; 
var KEY_DOWN_ARROW	= 40;
var KEY_UP_ARROW	= 38;
var KEY_RIGHT_ARROW	= 39;
var KEY_LEFT_ARROW	= 37;

function TypeaheadField(varname, url, inputs)
{
	if(typeof(varname) == "undefined")	{ return; }
	if(typeof(url) == "undefined")		{ return; }
	if(typeof(inputs) == "undefined")	{ return; }
	if(!inputs.target_node)				{ return; }

	var _self = this;
	
	this.callbacks = 
	{
		onClick:{
			callback_name:inputs.onClick,
			call:function(selected_row_index)
			{
				eval(inputs.onClick+'('+selected_row_index+')');
			}
		},
		onMouseOver:{
			callback_name:inputs.onMouseOver,
			call:function(element, row_index) 
			{
				if(_self.selected_row != null)
				{
					_self.selected_row.style.backgroundColor = '#EEE';
				}

				_self.selected_row_index = row_index;
				_self.selected_row = element;
				_self.selected_row.style.backgroundColor = '#ccc';

				if(inputs.onMouseOver)
				{
					eval(inputs.onMouseOver+'(element)');
				}
			}
		},
		onComplete:{
			callback_name:inputs.onComplete,
			call:eval(inputs.onComplete)
		},
		onArrowUp:{
			callback_name:inputs.onArrowUp,
			call:function()
			{
				var row_index = _self.selected_row_index - 1;
				
				if($('typeahead_row_'+row_index) != null)
				{
					if(_self.selected_row != null)
					{
						_self.selected_row.style.backgroundColor = '';
					}					
				
					_self.selected_row_index = row_index;
					_self.selected_row = $('typeahead_row_'+row_index);
					_self.selected_row.style.backgroundColor = '#ccc';
				}	

							
				//now try to callback
				if(inputs.onArrowUp)
				{
					eval(inputs.onArrowUp+'()');
				}
			}
		},
		onArrowDown:{
			callback_name:inputs.onArrowDown,
			call:function()
			{
				var row_index = _self.selected_row_index + 1;

				if($('typeahead_row_'+row_index) != null)
				{
				
					if(_self.selected_row != null)
					{
						_self.selected_row.style.backgroundColor = '';
					}
									
					_self.selected_row_index = row_index;
					_self.selected_row = $('typeahead_row_'+row_index);
					_self.selected_row.style.backgroundColor = '#ccc';
				}	
							
				//now try to callback
				if(inputs.onArrowDown)
				{
					eval(inputs.onArrowDown+'()');
				}
			}
		}
	};	
	
	this.input_value = '';
	this.intervalId = null;
	this.parent_node = inputs.target_node;	
	this.url = url;
	this.variable_name = varname;
	this.selected_row = null;
	this.selected_row_index = -1;

	//-----------
	/**
	 *
	 */	
	this.init = function()
	{
		//update any onmousedown events to hide the listdiv
		var _onmousedown = document.onmousedown;
		document.onmousedown = function(e)
		{
			if (!e) var e = window.event;
			if (e.target) targ = e.target;
			else if (e.srcElement) targ = e.srcElement;
			if (targ.nodeType == 3) // defeat Safari bug
				targ = targ.parentNode;			
			
			if((targ.nodeName.toLowerCase() != 'a') && (targ.id.indexOf('typeahead_') == -1))
			{
				$('listdiv').hide();	
			}
			
			if(typeof(_onmousedown) == 'function')
			{
				_onmousedown();
			}
		}
		
		var html = '<input type="text" id="typeahead_field" name="" onfocus="'+_self.variable_name+'.event_focus(this, event)" onkeyup="'+_self.variable_name+'.event_keyup(this, event)" class="cityEntry" />';
		$(_self.parent_node).innerHTML = html;
	}
	
	//-----------
	/**
	 *
	 */		
	this.cancel_request = function()
	{
		window.clearInterval(this.intervalId);
		this.intervalId = null;		
	}

	//-----------
	/**
	 *
	 */	
	this.request = function()
	{
		this.cancel_request();

		//support using jObject
		var jo = new jObject(this.url, this.callbacks.onComplete.callback_name);
		jo.add("search", this.input_value);
		jo.call();
	}           

	//-----------
	/**
	 *
	 */	
	this.schedule_request = function(force_request)
	{
		var interval_time = (force_request == true)?1:150;
		
		if(this.intervalId != null)
		{
			this.cancel_request();
		}
		
		this.intervalId = window.setInterval(_self.variable_name+'.request()', interval_time);
	}
	
	//-----------
	/**
	 * onfocus event handler
	 * If there is already a value in the field, we should request for data upon focus so we can draw
	 * the list
	 */		
	this.event_focus = function(inputField, e)
	{
		try
		{                       
			var value = trim(inputField.value);

			/*
			 * If field value length is 3 then its empty. 
			 * Clear field mem, cancel current request, callback with no data.
			 */
			if(value.length < 3)
			{
				this.input_value = '';
				this.cancel_request();				
				return;
			}			
			this.schedule_request(true);			
		}
		catch(e)
		{
			//do nothing
			//log error?
			//alert("Error trapped in event_keyup.\n" + e);
		}
	}	
	
	//-----------
	/**
	 *
	 */
	this.event_keyup = function(inputField, e)
	{
		var force_request = false;
		var keycode = '';
		
		try
		{                       

			var evt = (e)?e:(window.event)?window.event:null;
			if(evt)
			{
				keycode = (evt.charCode)?evt.charCode:((evt.keyCode)?evt.keyCode:((evt.which)?evt.which:0));
			}
			
			var value = trim(inputField.value);

			/*
			 * If field value length is <3 then its empty. 
			 * Clear field mem, cancel current request, callback with no data.
			 */
			if(value.length < 3)
			{
				this.input_value = '';
				this.cancel_request();				
				
				if(this.callbacks.onComplete.call)
				{
					this.callbacks.onComplete.call();
				}				
				
				return;
			}			
			
			//handle specific key events
			switch(keycode)
			{
				case KEY_ENTER:
					if(this.selected_row != null)
					{
						if(this.callbacks.onClick)
						{
							this.callbacks.onClick.call(this.selected_row_index);
						}
					}
					else
					{
						force_request = true;
						this.schedule_request(force_request);
					}
					break;

				case KEY_DOWN_ARROW:
					if(this.callbacks.onArrowDown.call)
					{
						this.callbacks.onArrowDown.call();
					}
					break;
				
				case KEY_UP_ARROW:
					if(this.callbacks.onArrowUp.call)
					{
						this.callbacks.onArrowUp.call();
					}
					break;
					
				case KEY_RIGHT_ARROW:
				case KEY_LEFT_ARROW:
					break;

				default:
					this.selected_row_index = -1;
					break;
			}

			
			//if stored value is same as current input value
			if(value == this.input_value)
			{
				return;
			}
			
			//store new value
			this.input_value = value;
						
			//schedule request for data
			this.schedule_request(force_request);			
		}
		catch(e)
		{
			//do nothing
			//log error?
			//alert("Error trapped in event_keyup.\n" + e);
		}
	}
}

//------------------
/**
 * Trims whitespace and new line characters from the end of the string
 */
function trim(value)
{
	var ltrim_regexp = /^\s*/;
	var rtrim_regexp = /\s$/;
	if(ltrim_regexp.test(value)) { value = value.replace(ltrim_regexp, ''); }
	if(rtrim_regexp.test(value)) { value = value.replace(rtrim_regexp, ''); }
	return value;
}






