/*
 * PathAC()
 *
 * An AutoComplete object
 * Redone by gp.
 */


 
function PathAC(input, uri, param) {
	var ac				= this; // To be used later on.
	this.doSubmit			= true;
	this.input			= input;
	this.input.setAttribute		( "autocomplete", "OFF" ); //Safety
	this.input.form.onsubmit	= function() { return ac.submit() };
	this.uri			= uri;
	this.param			= param;
	this.max			= 15;
	this.delay 			= 100;
		
	this.cache			= {};
	
	this.input.onkeydown		= function (event)  { return ac.onkeydown(this, event); };
	this.input.onkeyup		= function (event)  { ac.onkeyup(this, event) };
	this.input.onblur		= function () 		{ ac.hidePopup() };
	
	this.popup			= document.createElement('div');
	this.popup.className		= "autocomplete";
	this.popup.id			= "autocId"; // used in WCHhider
	this.popup.owner		= this;

	this.isSearching		= false;
	this.autoSelect			= true;

};


/**
 * Prevents the form from submitting if the suggestions popup is open
 */
PathAC.prototype.submit = function () {
	var popup = this.popup;	
	
	if (popup) {
		this.hidePopup();
	}
	
	
	if( this.doSubmit )
	{
		return true;
	}
	else 
		return false;
}

/**
 * Hides the autocomplete suggestions
 */
PathAC.prototype.hidePopup = function (keycode) {
	if (this.selected && ((keycode && keycode != 46 && keycode != 8 && keycode != 27) || !keycode)) {

		this.input.value = this.selected.autocompleteValue.replace( /(<em>|#).*?$/gi,"" ).replace( /<.*?>/gi , "" ).trim();
		this.autocompleteId = this.selected.autocompleteId;
		this.autocompleteValue = this.input.value;
	}
  
	// Remove n' hide
	if (this.popup.parentNode && this.popup.parentNode.tagName) {
		WCH.Discard('autocId');
		removeNode(this.popup);
	}
  	this.selected = false;
}


/**
 * Handler for the "keydown" event
 */
PathAC.prototype.onkeydown = function (input, e) {

	// Sanity check
	if ( this.timer )
                clearTimeout(this.timer);
	
	e =  e ? e : window.event;
	switch (e.keyCode) {
	    case 40: // down arrow
    	  this.selectDown();
	      return false;
	    case 38: // up arrow
    	  this.selectUp();
	      return false;

    	default: // all other keys
	      return true;
	  }
}

/**
 * Handler for the "keyup" event
 */
PathAC.prototype.onkeyup = function (input, e) {
	e =  e ? e : window.event;
	switch (e.keyCode) {
	    case 16: // shift
    	case 17: // ctrl
	    case 18: // alt
	    case 20: // caps lock
	    case 33: // page up
	    case 34: // page down
	    case 35: // end
	    case 36: // home
	    case 37: // left arrow
	    case 38: // up arrow
    	case 39: // right arrow
	    case 40: // down arrow
		return true;

	case 9:  // tab
    	case 13: // enter
    	case 27: // esc
		this.hidePopup(e.keyCode);
		return true;

	default: // all other keys
		if (input.value.length > 0 )
		{
			this.populatePopup();
		}
		else
			this.hidePopup(e.keyCode);
		return true;
	}
}

/**
 * Puts the currently highlighted suggestion into the autocomplete field
 */
PathAC.prototype.select = function (node) {
	this.input.value = node.autocompleteValue;
}

/**
 * Highlights the next suggestion
 */
PathAC.prototype.selectDown = function () {
	if (this.selected && this.selected.nextSibling) {
		this.highlight(this.selected.nextSibling);
	}
	else {
		var lis = this.popup.getElementsByTagName('li');
		if (lis.length > 0) {
			this.highlight(lis[0]);
		}
  	}
}

/**
 * Highlights the previous suggestion
 */
PathAC.prototype.selectUp = function () {
	if (this.selected && this.selected.previousSibling) {
		this.highlight(this.selected.previousSibling);
	}
}

/**
 * Highlights a suggestion
 */
PathAC.prototype.highlight = function (node) {
	removeClass(this.selected, 'selected');
	addClass(node, 'selected');
	this.selected = node;
	document.getElementById("area").value = this.selected.autocompleteId;
}

/**
 * Unhighlights a suggestion
 */
PathAC.prototype.unhighlight = function (node) {
	removeClass(node, 'selected');
	this.selected = false;
}

/**
 * Positions the suggestions popup and starts a search
 */
PathAC.prototype.populatePopup = function () {
	var ac					= this;
	var pos					= getXY(this.input);
	this.selected			= false;
	
	this.rePos();
	this.search(this.input.value);
}


/**
 * Fills the suggestion popup with any matches received
 */
PathAC.prototype.found = function (matches) {
	while (this.popup.hasChildNodes()) {
    	this.popup.removeChild(this.popup.childNodes[0]);
	}
	
		
	var ol = document.createElement('ol');
	var ac = this;
	
	// lets do it server side.
	if (matches.length > 0) {
		cnt = 0;
		for (i in matches) {
			if( !matches[i] )
				continue;
			cnt ++;
			li = document.createElement('li');
			div = document.createElement('div');
			div.innerHTML = matches[i].replace( /#.*?$/gi, "" );
			li.appendChild(div);
			
			li.autocompleteValue = matches[i];

			/* Get the id - if any */
			lala = matches[i] + "";
			idMatch = lala.match( /#(.*)$/i );
			if( idMatch )
				li.autocompleteId = idMatch[1];
			
			li.onmousedown = function() { ac.select(this); };
			li.onmouseover = function() { ac.highlight(this); };
			li.onmouseout  = function() { ac.unhighlight(this); };
			ol.appendChild(li);
			if ( cnt  >= this.max )
				break;
		}
		
		this.popup.appendChild(ol);
		if( this.autoSelect && matches.length == 1)
		{
			if( this.input.value.toUpperCase() == matches[0].toUpperCase() )
			{
				alert( "bingo");
			}
		}
	}
	else
	{
		this.hidePopup();
	}

	// Attach it to the body, if no there already.
	if ((!this.popup.parentNode || !this.popup.parentNode.tagName) && matches.length > 0) {
		document.getElementsByTagName('body')[0].appendChild(this.popup);
		WCH.Apply('autocId'); //hide select boxes under this @ ie
	}
	

	removeClass(this.input, 'loading');
	
}


PathAC.prototype.rePos = function () {

	if( !this.input)
		return false;
	

	var pos			= getXY(this.input);

	paddingLeft		= parseInt( getStyle( this.input, "paddingLeft" ) );

	this.popup.style.top	= (pos.y + this.input.offsetHeight) +'px';
	this.popup.style.left	=  ( pos.x + paddingLeft )   +'px';
	this.popup.style.width	= (this.input.offsetWidth ) +'px';
}

/**
 * Performs a cached and delayed search
 */
PathAC.prototype.search = function(searchString) {
	this.searchString = searchString;
	
	if (this.cache[searchString] && !this.isSearching && this.input.value == this.searchString) {
		
    	return this.found(this.cache[searchString]);
	}
	if (this.timer) {
		clearTimeout(this.timer);
	}
	var db = this;
	this.timer = setTimeout(function() {
		/* GP mega hit */
		if( db.input.value != searchString )
			return false;
		db.isSearching = true;							 
	    addClass(db.input, 'loading');
	rnd = Math.round( Math.random( 10000) );
	rnd += parseInt((new Date()).getTime());
    	HTTPGet(db.uri +'?q='+ searchString + "&add=" + db.param + "&rnd=" + rnd, db.receive, db);
	  },
	  this.delay);
}

/**
 * HTTP callback function. Passes suggestions to the autocomplete object
 */
PathAC.prototype.receive = function(string, xmlhttp, acdb) {
	if (xmlhttp.status != 200) {
		removeClass(acdb.input, 'throbbing');
		return alert('An HTTP error '+ xmlhttp.status +' occured.\n'+ this.uri);
	}
	
	// Split into array of key->value pairs
	var matches = string.length > 0 ? string.split('\n') : [];
	
	acdb.isSearching				= false;
	
	// Safety reasons
	if( acdb.input.value == acdb.searchString )
		acdb.cache[acdb.searchString]	= matches;

	acdb.found(matches);
}
