//
// All autocompleters that are registered
//
var AutoCompleters = new Array();

/**
 * Function for registering a new auto completer
 * 
 * @param control_id
 *            string Array identifier
 * @param source
 *            string Textfield to observe
 * @param multi_select
 *            bool Allow multi selection or not
 * @param callback_url
 *            string Callback URL to the server
 * 
 * @access public
 * @return AutoCompleter
 */

function register_autocompleter(control_id, source, multi_select, callback_url) {

	// 
	// Controleer ofals dit control_id al bestaat, zoja destroy het en maak het opnieuw aan
	//
	
	if (AutoCompleters[control_id]) {
		AutoCompleters[control_id] = null;
	} // end if

	//
	// Create the AutoCompleter
	//
	
	var instance = new AutoCompleter(control_id, source, multi_select, callback_url);
	AutoCompleters.push(instance);
	
	// initialize
	instance.init();
	
	// Return the autocompleter
	return instance;

}

/**
 * AutomCompleter that will display popups by textfields that wants a auto-completer
 *
 * @param    control_id        	string          Array identifier
 * @param    source            	string          Textfield to observe
 * @param    multi_select    	bool            Allow multi selection or not
 *
 * @access   public
 * @return   AutoCompleter
 */
function AutoCompleter(control_id, source, multi_select, callback_url) {

	/**
	 * Variablen beheer binnen de klasse, methods and propertys
	 *
	 * @var        selectedIndex           	int           Selected index in the popup
	 * @var        menu_items            	Array         Results
	 * @var        multiple_names    		Bool          Mogen meerdere namen of niet ?
	 * @var        txt                     	Object        Tekst object
	 * @var        container               	Object        Div waar alle resultaten inkomen
	 * @var        control                   String        String waar de this.name van de klasse object in opgeslagen is
	 * @var        menu_open              	Bool          Is het menu zichtbaar of niet ?
	 * @var        max_names              	int           Maximaal aantal resultaten weer te geven in popup
	 * @var        root                      String        Root naar waar ajax.php staat
	 * @var        me                        Object        Referentie naar de root van de class, zodat je de variablen die hier als this gelden vanuit private functies kunt aanroepen met me. ipv this.
	 */
	this.selectedIndex = 0;
	this.suggestions = new Array();
	this.multi_select = false;
	this.source = source;
	this.container = null;
	this.control_id = control_id;
	this.popup_open = false;
	this.max_suggestions = 5;
	this.callbackURL = callback_url;
	this.first_build = true;
	
	// Backreference
	var me = this;
	
	this.init = function()
	{
		
	  me.container             = document.createElement( 'div' );
	  me.container.className   = 'autocomplete_suggestions_container';
	  
	  var pos                    = findPos( me.source );	  	  	  
	  
	  me.container.style.left    = pos[0] + 'px';
	  me.container.style.top     = (pos[1] + $(me.source).height() + 15) + 'px';	  
	  me.container.style.display = 'none';
	  
	  $(me.container).appendTo(document.body);
	  
	  // Bind key-up handler for refreshing the popup
	  $(this.source).keyup(this.reload);
	  
	  // onblur listener for closing the popup
	  $(this.source).blur(me.close_popup);
	}
	
	
	/**
	 * Closes/hides the popup
	 * 
	 * @return void
	 */
	this.close_popup = function() {
		
		$(me.container).slideUp(300); // @todo: make fadeOut time dynamic
		
		me.selectedIndex = 0;
		me.popup_open = false; // set flag				
	}

	/**
	 * Opens/shows the popup
	 * @return void
	 */
	this.open_popup = function() {
		 				 
		 // Close all other opened popups
		 for( var i=0; i<AutoCompleters.length; i++ )
		 {			
			 if( AutoCompleters[i].control_id != me.control_id )
			 {
				 AutoCompleters[i].close_popup();
			 }
		 }
				
		$(me.container).slideDown(300); // @todo: make fadein time dynamic
		me.popup_open = true;
	}
	 
 	/**
	 * Empties the popup
	 * @return void
	 */
	this.empty_popup = function() {
		
	}
		
	/**
	 * Sets the callback URL
	 */
	this.setCallbackURL = function(sURL) {
		me.callbackURL = sURL;
	}

	/**
	 * Returns the callback URL
	 */
	this.getCallbackURL = function() {
		return me.callbackURL;
	}

	/**
	 * Sets the maximum suggestions
	 * @param int iMaxSuggestions
	 */
	this.setMaxSuggestiosn = function(iMaxSuggestions) {
		me.max_suggestions = iMaxSuggestions;
	}

	/**
	 * Returns the maximum suggestions
	 * @return int
	 */
	this.getMaxSuggestions = function() {
		return me.max_suggestions;
	}

	/**
	 * Reloads the popup data
	 */
	this.reload = function(e) {
		var sValue = this.value;

		if (sValue == '') {			
			// Close the popup
			me.close_popup();
		}

		// get pressed key
		var sKey = ( e.keyCode ) ? e.keyCode : e.charCode;
		switch (sKey) {
		case 13: // VK_RETURN

			me.set_value(me.selectedIndex);
			break;

		case 27: // VK_ESCAPE

			me.close_popup();
			break;

		case 38: // VK_UP

			var index = me.selectedIndex;
			// Check if index is higher then 0, if so, decrease index with 1
			if( index > 0 )
			{
				index--;
			} else {
				index = (me.suggestions.length-1);
			}
			
			// set the selected item
			me.set_selected(index);
		
			break;

		case 40: // VK_DOWN

			var index = me.selectedIndex;
			// Check if index is higher then 0, if so, decrease index with 1
			if( index < (me.suggestions.length-1) )
			{
				index++;
			} else {
				index = 0;
			}
			
			// set the selected item
			me.set_selected(index);
			break;
		default:

			// get new suggestions
			$.get(me.getCallbackURL() + '/' + escape(sValue) + '/' + escape(me.getMaxSuggestions()), {}, me.suggestionsLoaded, 'xml');

			break;
		} // end switch
	}

	/**
	 * Sets the currently selected item as value
	 */
	this.set_value = function(index) {
		 if( me.suggestions[index] )
		 {
			 me.source.value = (me.suggestions[index].label);
			 
			 // close the popup
			 me.close_popup();
		 }
	}
	 
	 /**
	  * Sets the given item selected
	  * @param index
	  * @return void
	  */
	 this.set_selected = function (index)
	 {
		 if( me.suggestions[index] )
		 {
			 // Make the current selected item in-active
			 $(me.suggestions[me.selectedIndex]['td']).removeClass('hover');
			 
			 // Add class to the new index
			 $(me.suggestions[index]['td']).addClass('hover');
			 
			 // Update the selected index
			 me.selectedIndex = index;			 
		 }
		 		 
	 }
	 
	/**
	 * Called when the suggestions are loaded
	 * @param xml
	 * @return void
	 */
	this.suggestionsLoaded = function(xml) {
						 
		// Reset the array with suggestions
		me.suggestions = new Array();

		$(xml).find('suggestion').each( function() {
			var suggestion = new Array();
			$(this.attributes).each( function() {
				suggestion[this.nodeName] = this.nodeValue;
			});
							
			// Add the suggestion
				me.suggestions.push(suggestion);
			});				
		
		// Build the popup
		me.build();
		
		if( me.suggestions.length > 0 )
		{
			// Display
			me.open_popup();
			
			// Set the first item selected
			me.set_selected(0);
		}
	}

	

	/**
	 * Builds the popup
	 * @return void
	 */
	this.build = function() {

		// Empty the popup first
		//me.empty_popup();
		
		if( me.suggestions.length == 0 )
		{
			// close the popup
			me.close_popup();
						
		} else { // suggestions found 
			
			// Create a new table element
			var table = document.createElement("table");
			table.cellPadding = 4;
			table.cellSpacing = 1;
			table.border = 1;
			table.id = me.control_id+"_container";
			//table.className = ""; // @todo:
			// make
			// the
			// classname
			// dynamic
	
			// Declare suggestions so it is easy to pick suggestions from param
			// (maybe version 1.1) for making it more generic
			var suggestions = me.suggestions;
			
			// Loop through the suggestions and add them to the table
			for ( var i = 0; i < suggestions.length; i++) 
			{
				
				// Create a new row
				var tr = document.createElement('tr');
				var td = document.createElement('td');
				tr.appendChild(td);
				
				// Add the td
				table.appendChild(tr);
				
				// Fill the table cell
				td.innerHTML = suggestions[i]['label'];
				
				// Set the classname
				td.className = ('suggestion' + ((i == me.selectedIndex) ? ' hover' : ''));
				td.style.width = "100%";
				
				// table.autocomplete_suggestions_container.suggestion
				// table.autocomplete_suggestions_container.suggestion .selected
				// Assign events
				td.onmouseover 		= AutoCompleterSuggestion.prototype.onmouseover;
				td.onclick 			= AutoCompleterSuggestion.prototype.onmouseclick;
				td.onmouseout 		= AutoCompleterSuggestion.prototype.onmouseout;
				
				// save the instance of the table cell into the suggestion
				suggestions[i]['td'] = td;
				
				// Set control_id
				td.control_id 		= me.control_id;
				
				// set the index
				td.listIndex		= i;
				
			} // end for 
	
			me.container.innerHTML = '';
			me.container.appendChild(table);
		}
	} // end this.build
}

function AutoCompleterSuggestion() {
}

AutoCompleterSuggestion.prototype.onmouseover = function(e) 
{
	for( var i=0; i<AutoCompleters.length; i++ )
	{
		if( AutoCompleters[i].control_id == this.control_id )
		{
			AutoCompleters[i].set_selected(this.listIndex);
			break; // break out of the for loop
		}
	}
	
	$(this).addClass('hover');
}

AutoCompleterSuggestion.prototype.onmouseout = function(e) 
{
	/*for( var i=0; i<AutoCompleters.length; i++ )
	{
		if( AutoCompleters[i].control_id == this.control_id )
		{
			AutoCompleters[i].set_selected(this.listIndex);
			break; // break out of the for loop
		}
	}
	$(this).removeClass('hover');*/
}

AutoCompleterSuggestion.prototype.onmouseclick = function(e) {
	for( var i=0; i<AutoCompleters.length; i++ )
	{
		if( AutoCompleters[i].control_id == this.control_id )
		{
			AutoCompleters[i].set_value(this.listIndex);
			break; // break out of the for loop
		}
	}
}

