var AutoCompliteController = new Object();
	
AutoCompliteController = {
	version : '2.0.0',
	author : 'ToshaUst',
	insts : Array(),
	debug : false,
	
	getAc : function (name,rpc)
	{
		var tmpAc = new AutoCompliter(name,rpc);
		var i = this.insts.length;
		tmpAc.instIndex = i;
		tmpAc.Acc = this;
		this.insts[i] = tmpAc;
		return tmpAc;
	},
	
	getData : function(inputString,instIndex)
	{
		var inst = this.insts[instIndex];
		if(inst.getHandler != null)
		{
			clearTimeout(inst.getHandler);
			inst.getHandler = null;
		}
		inst.lastSearch = inputString;
		
		if(inputString.length == 0)
		{
			// Hide the suggestion box.
			$('#' + inst.divBoxId).hide();
		} else 
		{
			if(typeof(inst.rpc) == 'function')
			{
				var ar = inst.rpc(inputString);
				inst.setData(ar[0],ar[1],ar[2]);
			}
			else
			{
				var ajaxSettings = {
					dataType : 'xml',
					url : inst.rpc, 
					data : 'queryString='+inputString+'&instId='+inst.instIndex,
					success : this.setData,
					type : 'POST'}
					
				if(this.debug)
				{
					ajaxSettings.error = function() { alert('Ajax error'); }
				}
				
				$.ajax(ajaxSettings);
			}
		}
	},
	
	setData : function (xml)
	{
		var i = jQuery('instId',xml).text();
		AutoCompliteController.insts[i].setData(jQuery('data',xml).text(),jQuery('type',xml).text(),jQuery('count',xml).text());			
	},
	
	selectItem : function(inst,eItem)
	{
		var stop = 0;
	},
	
	move : function(delta,instIndex)
	{
		var inst = this.insts[instIndex];
		inst.move(delta);
	},
	
	hideList : function(instIndex)
	{
		var inst = this.insts[instIndex];
		if(inst.hideHandler != null)
		{
			clearTimeout(inst.hideHandler);
			inst.hideHandler = null;
		}
		$('#'+inst.divBoxId).hide();
		inst.listIsShow = false;
	}
}

function AutoCompliter(name,rpc)
{
	this.inputId = name + 'Input'
	this.divBoxId = name + 'ListBox'
	this.divListId = name + 'List'
	this.countId = name + 'Count'
	this.rpc = rpc
	this.browser = jQuery.browser
}

AutoCompliter.prototype = {
	version : '2.0.0',
	author : 'ToshaUst',
	listIsShow : false,
	selectedIndex : -1,
	itemsCount : -1,
	jqUL : null,
	keyHandler : null,
	lastSearch : '',
	getHandler : null,
	hideHandler : null,
	debug : true,
	lastMove : 0,
	itemsNodeIndex : Array(),
	disabled : false,
	withScroll : true,
	maxHeight : 250,
	fillCallback : null,
	get_delay : 500,
	hasList : false,
	
	getState : function()
	{
		var arState = new Object();
		for(var elem in this)
		{
			if(typeof(eval('this.'+elem)) != 'function')
			{
				eval('arState.'+elem+'=this.'+elem);
			}
		}
		
		return arState;
	},
	
	keyUp : function(event)
	{
		if(this.disabled) return true;
		
		var inpStr = $('#' + this.inputId).val();
		var cancelEvent = false;
		var getNeed = true;
		if(this.hasList)
		{
			if(event && event.keyCode)
			{
				//debuger.log("keyUp Code:" + event.keyCode);
				if(this.listIsShow)
				{
					var kc = event.keyCode;
					if(kc == 40 || kc == 38)
					{
						cancelEvent = true;
						getNeed = false;
						this.stopMove();
					}
					else if(kc == 13 && this.selectedIndex > -1)
					{
						cancelEvent = true;
						getNeed = false;
					}
				}
				
			}
		}
		
		
		if(inpStr == this.lastSearch) getNeed = false;
		
		if(getNeed)
		{
			if(this.getHandler != null) clearTimeout(this.getHandler);
			this.getHandler = setTimeout("AutoCompliteController.getData('"+inpStr+"',"+this.instIndex+")",this.get_delay);
		}
		
		event.cancelBubble = cancelEvent;
		return  !cancelEvent;
	},
	
	
	keyDown : function(event) 
	{
		if(this.disabled) return true;
		if(!this.hasList) return true;
		
		var cancelEvent = false;
		if(event && event.keyCode)
		{
			if(this.listIsShow)
			{
				var kc = event.keyCode
				//debuger.log("keyDown Code:" + kc);
				if(kc == 13 && this.selectedIndex > -1)
				{
					try
					{
						this.fill(this.jqUL[0].childNodes[this.itemsNodeIndex[this.selectedIndex]]);
					}
					catch(e) {}
					cancelEvent = true;
				}
				else if(kc == 40) 
				{
					this.startMove(1);
					cancelEvent = true;
				}
				else if(kc == 38) 
				{
					this.startMove(-1);
					cancelEvent = true;
				}
			}
		}
		event.cancelBubble = cancelEvent;
		return  !cancelEvent;
	},
	
	startMove : function(delta)
	{
		if(!this.browser.opera)
		{
			var d = new Date();
			var timeNow = d.valueOf();		
			if(this.lastMove + 50 < timeNow)
			{
				this.lastMove = timeNow;
				this.move(delta);
			}
		}
		else
		{
			
			this.move(delta);
			this.keyHandler = setInterval("AutoCompliteController.move("+delta+","+this.instIndex+")",100);
			//debuger.log("AutoCompliteController.move("+delta+","+this.instIndex+") start Handler:" + this.keyHandler);
		}
	},
	
	stopMove : function()
	{
		if(this.browser.opera)
		{
			if(this.keyHandler != null)
			{
				//debuger.log("stop interval Handler:" + this.keyHandler);
				clearInterval(this.keyHandler);
			}
		}		
	},
	
	selectItem : function(index)
	{
		if(this.selectedIndex > -1)
		{
			var SelectedNodeIndex = this.itemsNodeIndex[this.selectedIndex];
			$(this.jqUL[0].childNodes[SelectedNodeIndex]).removeClass('selected');
		}
		
		var NodeIndex = this.itemsNodeIndex[index];
		var jqSelectingItem = $(this.jqUL[0].childNodes[NodeIndex]);
		var eSelectingItem = jqSelectingItem[0];
		jqSelectingItem .addClass('selected');
		this.selectedIndex = eSelectingItem.i;
		
		if(this.withScroll)
		{
			var eScrollBox = eSelectingItem.parentNode.parentNode;
			var scrollTop = eScrollBox.scrollTop;
			var heightBox = $(eScrollBox).height();
			var heightElement = this.getElementRealHeight(eSelectingItem);
			var offsetTop = eSelectingItem.offsetTop;
			var maxScrollTop = this.getElementRealHeight(eSelectingItem.parentNode) - heightBox;
			
			var topDelta = offsetTop - scrollTop;
			if(topDelta + heightElement > heightBox)
			{
				eScrollBox.scrollTop = offsetTop - heightBox + heightElement;
			}
			
			if(topDelta < 0)
			{
				if(offsetTop > maxScrollTop) offsetTop = maxScrollTop;
				eScrollBox.scrollTop = offsetTop;
			}
			var stop = 0;
		}
	},
	
	getElementRealHeight : function(elem)
	{
		var jqElem = $(elem);
		var Height = $(elem).height();
		Height += this.getCSSSizeVal($(elem).css('padding-top'));
		Height += this.getCSSSizeVal($(elem).css('padding-bottom'));
		Height += this.getCSSSizeVal($(elem).css('margin-top'));
		Height += this.getCSSSizeVal($(elem).css('margin-bottom'));
		
		return Height;
	},
	
	getCSSSizeVal : function(str)
	{
		return str.replace(new RegExp('[^0-9]','gi'),'')*1;
	},	
	
	disable : function()
	{
		this.disabled = true;
		AutoCompliteController.hideList(this.instIndex);
	},
	
	setData : function(data,type,count)
	{
		this.listIsShow = false;
		this.selectedIndex = -1;
		
		
		var jqDivList = $('#' + this.divListId);
		var jqDivBox = $('#' + this.divBoxId);
		var jqControlTable = jqDivBox.find('.controlTable');
		
		if(type == 'html')
		{
			this.hasList = true;
			jqDivList.html(data);
			this.jqUL = $(jqDivList[0].childNodes[0]);
			var eUL = this.jqUL[0];
			if(eUL.nodeType == 1)
			{
				this.jqUL[0].AC = this;
				var child,i=0;
				for(var j=0,len=eUL.childNodes.length; j<len;j++)
				{
					child = eUL.childNodes[j];
					if(child.nodeType == 1)
					{
						child.i = i;
						this.itemsNodeIndex[i] = j;
						child.onmouseover = function() { this.parentNode.AC.selectItem(this.i); };
						child.onclick = function() { if(this.parentNode.AC.fill) this.parentNode.AC.fill(this); };
						i++;
					}
				}
				this.itemsCount = i;
				jqControlTable.show();
				var jqCount = $('#' + this.countId);
				if(jqCount.length > 0)
				{
					jqCount.empty();
					jqCount.append(count);
				}
				this.showList();
				
			}
			var stop = 0;
		}
		else 
		{
			this.hasList = false;
			jqControlTable.hide();
			if(this.debug)
			{
				jqDivList.html(data);
				jqDivBox.show();
				this.listIsShow = true;
			}
		}
		
		
	},
	
	showList : function()
	{
		var jqDivList = $('#' + this.divListId);
		var jqDivBox = $('#' + this.divBoxId);
		var jqInput = $('#' + this.inputId);
		
		jqDivList.css('visibility','hidden');
		jqDivBox.show();
		var height = jqDivList.height();
		
		this.maxHeight = this.getCSSSizeVal(jqDivList.css('max-height'));
		
		if(height > this.maxHeight)
		{
			jqDivList.height(this.maxHeight);
		}
		
		var cssWidth = this.getCSSSizeVal(jqDivBox.css('width'));
		var width = jqInput.width();
		if(cssWidth <= 0 || cssWidth < width)
		{
			jqDivBox.css('width',width);
		}
		
		jqDivList.css('visibility','');
		
		this.listIsShow = true;
	},
	
	fill : function (eItem) 
	{
		var val = $(eItem).attr('m_val');
		$('#'+this.inputId).val(val);
		$('#'+this.divBoxId).hide();
		this.listIsShow = false;
		this.lastSearch = val;
		$('#'+this.inputId)[0].focus();
		if(this.fillCallback != null)
		{
			this.fillCallback(eItem);
		}
	},
	
	move : function(delta)
	{
		var nextIndex = this.selectedIndex+delta;
		if(delta >=0)
		{
			if(nextIndex >= this.itemsCount) nextIndex = 0;
		}
		else
		{
			if(nextIndex < 0) nextIndex = this.itemsCount-1;
		}
		this.selectItem(nextIndex);
	},
		
	hideList : function ()
	{
		if(this.hideHandler != null) clearTimeout(this.hideHandler);
		this.hideHandler = setTimeout("AutoCompliteController.hideList("+this.instIndex+")",200);
	}
}

function Debbuger(id)
{
	this.id = id
}

Debbuger.prototype = {
	log : function(msg)
		{
			$('#' + this.id)[0].value += msg + "\r\n";
		}
}

var debuger = new Debbuger('debugtextarea');