function $()
{
	var elements = new Array();

	for (var i = 0; i < arguments.length; i++)
	{
		var element = arguments[i];

		if (typeof element == 'string')
			element = document.getElementById(element);

		if (arguments.length == 1)
			return element;

		elements.push(element);
	}

	return elements;
}

var $A = function(iterable)
{
	if (!iterable) return [];

	if (iterable.toArray)
	{
		return iterable.toArray();
	}
	else
	{
		var results = [];

		for (var i = 0; i < iterable.length; i++)
			results.push(iterable[i]);

		return results;
	}
}

Function.prototype.bind = function()
{
	var __method = this, args = $A(arguments), object = args.shift();

	return function()
	{
		return __method.apply(object, args.concat($A(arguments)));
	}
}

if(typeof(XMLHttpRequest) == "undefined")
{
	var XMLHttpRequest = function()
	{
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
}

function CSuggestion(fieldName)
{
	this.objField = $(fieldName);
	this.lastRequest = '';
	this.timer = false;
	this.hideTimeOut = 100;
	this.searchUrl = '';
	this.searchKey = '';
	this.searchTarget = '';
	this.selectedIndex = -1;
	this.timeoutID = -1;
	this.fieldSearchText = 'Enter a ticker or company...'
	this.containerName = 'suggestion_' + fieldName;

	this.requests = new Array();
}

CSuggestion.prototype =
{
	init: function(obj)
	{
		this.searchUrl				= obj.searchUrl ? obj.searchUrl : '';
		this.searchKey				= obj.searchKey ? obj.searchKey : '';
		this.searchTarget			= obj.searchTarget ? obj.searchTarget : '';
		this.requestUrl				= obj.requestUrl ? obj.requestUrl : '';

		this.objField.onkeyup 		= this.getStrings.bind(this);
		this.objField.onclick 		= this.onFieldClick.bind(this);
		this.objField.value			= this.fieldSearchText;
		this.objField.onmouseover 	= this.hideTimerReset.bind(this);

		if (document.all && !window.opera)
		{
			var _this = this;

			setTimeout(function() {
				document.body.onclick = _this.handleWindowClick.bind(_this);
			}, 1);
		}
		else
		{
			window.onclick = this.handleWindowClick.bind(this);
		}
	},

	handleWindowClick: function(evt)
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);
		var target = (evt.target) ? evt.target : evt.srcElement;

		if (target == this.objField) {
			return true;
		}

		var objContainer = this.createContainer();

		while (target)
		{
			if (target == objContainer) return true;
			target = target.parentNode;
		}

		objContainer.style.display = 'none';
		return true;
	},

	resetSelectedIndex: function()
	{
		this.selectedIndex = -1;
	},

	callRequest: function(value)
	{
		this.timeoutID = -1;

		if (value == '')
		{
			return;
		}

		this.request(this.requestUrl + value, value);
		this.lastRequest = value;
		this.resetSelectedIndex();
	},

	onFieldClick: function()
	{
		if (this.objField.value == this.fieldSearchText)
		{
			this.objField.value = '';
		}
		else
		{
			var selfPtr = this;
			var val = this.objField.value;
			this.timeoutID = setTimeout(function() { selfPtr.callRequest(val) }, 50);
		}
	},

	getStrings: function(evt)
	{
		evt = evt ? evt : window.event;
		var srcEl = (evt.target) ? evt.target : evt.srcElement;

		if (srcEl && srcEl.value != this.lastRequest)
		{
			if (evt.keyCode != 38 && evt.keyCode != 40 && evt.keyCode != 9)
			{
				if (this.timeoutID > -1)
				{
					clearTimeout(this.timeoutID);
				}

				var selfPtr = this;
				this.timeoutID = setTimeout(function() { selfPtr.callRequest(srcEl.value) }, 50);
			}
		}

		if (srcEl.value == '')
		{
			this.hideSuggestions('');
		}
	},

	clearSelected: function()
	{
		for (i = 0; i < 20; i++) //20? how many links?
		{
			var nowCompany = document.getElementById('company_' + i);
			var nowTicker = document.getElementById('ticker_' + i);

			if (nowCompany && nowTicker)
			{
				nowCompany.className = 'search_finded_company';
				nowTicker.className = 'search_finded_symbol';
			}
		}

		var allResults = document.getElementById('all_results_link');

		if (allResults) {
			allResults.className = 'search_finded_company';
		}
	},

	onMouseOverDiv: function (evt)
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);
		var target = (evt.target) ? evt.target : evt.srcElement;

		//this.selectedIndex = target.rel;
		var id = target.id.split('_')[1];
		this.selectedIndex = id;

		this.clearSelected();

		document.getElementById('company_' + id).className = 'search_finded_company over';
		document.getElementById('ticker_' + id).className = 'search_finded_symbol over';
	},

	onMouseOutDiv: function (evt)
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);
		var target = (evt.target) ? evt.target : evt.srcElement;

		var id = target.id.split('_')[1];
		this.selectedIndex = -1;

		document.getElementById('company_' + id).className = 'search_finded_company';
		document.getElementById('ticker_' + id).className = 'search_finded_symbol';
	},

	request: function(url, query)
	{
		var tmp = new Object();
		var now = new Date();
		tmp.startTime = now.getTime();
		tmp.ended = null;

		this.requests.push(tmp);

		var req = null;

		try
		{
			req = new XMLHttpRequest();
		}
		catch(e)
		{
			return;
		}

		req.onreadystatechange = function()
		{
			if (req.readyState == 4)
			{
				if (req.status == 200)
				{
					try
					{
						if (this.objField.value == '') return;

						var objContainer = this.createContainer();
						var xml = req.responseXML;

						var end = new Date();
						var starttimes = xml.getElementsByTagName('starttime');

						if (!starttimes || !starttimes[0])
						{
							return;
						}

						starttimeTmp = starttimes[0];

						var starttime = starttimeTmp.firstChild.nodeValue;
						var index = -1;

						for (var i = 0; i < this.requests.length; i++)
						{
							var r = this.requests[i];

							if (r.startTime > starttime && tr.ended != null)
							{
								return;
							}
							if (r.startTime == starttime)
							{
								index = i;
							}
						}

						if (index == -1)
						{
							return;
						}

						this.requests[index].ended = 1;

						var words = xml.getElementsByTagName('words');

						if  (words && words[0])
						{
							objContainer.innerHTML = '';
							var word_arr = words[0].getElementsByTagName('word');

							if (word_arr && word_arr.length)
							{
								var caption = document.createElement('div');
								caption.innerHTML = '<div class="search_caption"><div class="search_caption_symbol">Symbol</div><div class="search_caption_company">Company</div></div><div class="search_spacer"></div>';
								objContainer.appendChild(caption);

								for (var i = 0; i < word_arr.length; i++ )
								{

									var word = document.createElement('A');
									word.id = 'link_' + i;
									word.style.display = 'block';

									var tickerDiv = document.createElement('DIV');
									var companyDiv = document.createElement('DIV');

									companyDiv.innerHTML = word_arr[i].firstChild.nodeValue;
									tickerDiv.innerHTML = word_arr[i].getAttribute('ticker');

									companyDiv.id = 'company_' + i;
									tickerDiv.id = 'ticker_' + i;

									companyDiv.className = 'search_finded_company';
									tickerDiv.className = 'search_finded_symbol';

									tickerDiv.onfocus = function (evt)
									{
										var evt = (evt) ? evt : ((window.event) ? event : null);
										var target = (evt.target) ? evt.target : evt.srcElement;
										this.objField.value = target.firstChild.nodeValue;
										this.objField.focus();

									}.bind(this);

									tickerDiv.onmouseover = this.onMouseOverDiv.bind(this);
									companyDiv.onmouseover = this.onMouseOverDiv.bind(this);

									tickerDiv.onmouseout = this.onMouseOutDiv.bind(this);
									companyDiv.onmouseout = this.onMouseOutDiv.bind(this);

									word.setAttribute('rel',i);
									word.setAttribute('href', word_arr[i].getAttribute('url'));//.replace('stock.cgi', 'stock_fromsearch.cgi'));
									word.setAttribute('target', this.searchTarget);

									word.onclick = function (evt)
									{
										var dat = new Date();
										dat.setTime(dat.getTime() + (2*60*1000));	// +2 mins
										SetCookie('SearchQuery', query, dat);
									}.bind(this);

									var space = document.createElement('DIV');
									space.className = 'search_spacer_invisible';

									word.appendChild(tickerDiv);
									word.appendChild(companyDiv);
									word.appendChild(space);

									objContainer.appendChild(word);
								}

								var allResults = document.createElement('DIV');
								allResults.className = 'search_all_results';
								allResults.id = 'all_results_' + this.containerName;
								allResults.innerHTML = '<a href="' + this.searchUrl + escape(query) + '"><div class="search_finded_company" id="all_results_link">Show all results for \'' + query + "'" + '</div></a>';

								objContainer.appendChild(allResults);

								objContainer.style.display = 'block';
							}
							else
							{
								objContainer.style.display = 'none';
							}
						}
					}
					catch (e){}
				}
			}
		}.bind(this);

		req.open('GET', url + '&starttime=' + tmp.startTime, true);
		//req.open('GET', url, true);
		req.setRequestHeader('x-requested-with', 'XMLHttpRequest');//
		req.send('');
	},

	hideSuggestions: function(text)
	{
		var elem = $(this.containerName);

		if (elem)
		{
			elem.style.display = 'none';

			this.lastRequest = '';
			this.resetSelectedIndex();

			if (typeof text == 'string')
			{
				this.objField.value = text;
			}
			else
			{
				this.objField.value = (this.objField.value != '' ?  this.objField.value : this.fieldSearchText);
			}
		}
	},

	hideTimerSet: function()
	{
		this.timer = setTimeout(this.hideSuggestions.bind(this), this.hideTimeOut);
	},

	hideTimerReset: function()
	{
		if (this.timer) clearTimeout(this.timer);
	},

	createContainer: function ()
	{
		if ($(this.containerName)) return $(this.containerName);

		var body = document.getElementsByTagName('body');

		if (body && body[0])
		{
			var container 				= document.createElement('DIV');
			container.id				= this.containerName;
			container.style.display 	= 'none';
			container.style.position 	= 'absolute';
			container.className = 'suggestions';
			container.onmouseover 		= this.hideTimerReset.bind(this);
			//container.onmouseout		= this.hideTimerSet.bind(this);
			body[0].appendChild(container);
			this.containerPosition(container);
		}
		return container;
	},

	setSuggestFocus: function (action)
	{
		if ($(this.containerName))
		{
			var els = $(this.containerName).getElementsByTagName('A');

			if (els)
			{
				var prevIndex = this.selectedIndex;

				if (action == 'down')
					this.selectedIndex += 1;
				else
					this.selectedIndex -= 1;

				if (this.selectedIndex < 0)
				{
					this.selectedIndex = els.length - 1;
				}
				else if (this.selectedIndex > els.length - 1)
				{
					this.selectedIndex = 0;
				}

				this.clearSelected();

				document.getElementById('all_results_link').className = 'search_finded_company';

				if (this.selectedIndex != els.length - 1)
				{
					document.getElementById('company_' + this.selectedIndex).className = 'search_finded_company over';
					document.getElementById('ticker_' + this.selectedIndex).className = 'search_finded_symbol over';
				}
				else
				{
					document.getElementById('all_results_link').className = 'search_finded_company over w330';
				}

				return;
			}
		}
	},

	gotoDefinition: function ()
	{
		if ($(this.containerName))
		{
 			var els = $(this.containerName).getElementsByTagName('A');

 			if (els && this.selectedIndex >= 0 && els[this.selectedIndex])
			{
				var t = els[this.selectedIndex].getAttribute('tag');

				location.href = els[this.selectedIndex].href;
				return true;
			}
		}

		return false;
	},

	handleArrowKeys: function (evt)
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);

	    if (evt)
	    {
	        switch (evt.keyCode)
	        {
	            case 38: //up
					this.setSuggestFocus('up');
					break;

	            case 40: //down
					this.setSuggestFocus('down');
					break;
	         }
	    }
	},

	checkBox: function()
	{
		this.MessageBox = null;
	},

	formSubmit: function()
	{
		if (this.objField)
		{
			if (SearchField != null && (SearchField.PHRASE == this.objField.value || this.objField.value == ''))
			{
				if (Ext != null && Ext.Msg != null)
				{
					if (typeof this.MessageBox == 'undefined' || !this.MessageBox)
					{
						this.MessageBox = Ext.Msg.show({
							title:'Warning',
							msg: '<br />Please enter a ticker or company in the search box, and try again.',
							buttons: Ext.Msg.OK,
							fn: this.checkBox.bind(this),
							animEl: 'submit_search',
							icon: Ext.MessageBox.WARNING,
							modal: false
						});
					}
				}
				else
				{
					alert('Please enter a ticker or company in the search box, and try again.')
				}

				return false;
			}
		}

		if (!this.gotoDefinition())
		{
			return true;
		}

		return false;
	},

	containerPosition: function ( container )
	{
		var left = this.getLeftPos(this.objField);
		var top = this.getTopPos(this.objField) + this.objField.offsetHeight + 2;

		container.style.left = left + 'px';
		container.style.top	= top + 'px';
	},

	getLeftPos: function (obj)
	{
		var res = 0;

		while (obj)
		{
			res += obj.offsetLeft;
			obj = obj.offsetParent;
		}

		return res;
	},

	getTopPos: function (obj)
	{
		var res = 0;

		while (obj)
		{
			res += obj.offsetTop;
			obj = obj.offsetParent;
		}

		return res;
	}
}