
Function.prototype.bindAsCallback = function(object)
{
	var fn = this;
	return function() { fn.apply(object, arguments); };
}

function AutoComplete(fieldid, popupid, url, emptyvalue)
{
	this.visible = false;
	this.selected_index = 0;
	this.first = false;
	this.blur_timeout = null;
	this.popup_timeout = null;
	this.url = url;
	this.data = [];

	this.field = $("input[@name='" + fieldid + "']");
	this.popup = $("#" + popupid);

	if(this.field.val() == '')
	{
		this.field.val(emptyvalue);
		this.first = true;
	}

	this.onblur = this.onblur.bindAsCallback(this);
	this.onfocus = this.onfocus.bindAsCallback(this);
	this.onkeyup = this.onkeyup.bindAsCallback(this);
	this.onkeypressed = this.onkeypressed.bindAsCallback(this);
	this.hide = this.hide.bindAsCallback(this);
	this.changed = this.changed.bindAsCallback(this);
	this.callback = this.callback.bindAsCallback(this);
	this.onhover = this.onhover.bindAsCallback(this);
	this.onclick = this.onclick.bindAsCallback(this);

	this.field.blur(this.onblur);
	this.field.focus(this.onfocus);
	this.field.keyup(this.onkeyup);
	this.field.keypress(this.onkeypressed);
}

AutoComplete.prototype.onfocus = function()
{
	if(this.first)
	{
		this.field.val('');
		this.first = false;
	}
}

AutoComplete.prototype.onblur = function()
{
	this.blur_timeout = setTimeout(this.hide, 500);
}

AutoComplete.prototype.hide = function()
{
	this.popup.hide();
	this.visible = false;
}

AutoComplete.prototype.onkeypressed = function(event)
{
	var key = event.keyCode;
	if (key == 13 && this.visible)
	{
		event.preventDefault();
		this.completeword();
	}
}

AutoComplete.prototype.onkeyup = function(event)
{
	var key = event.keyCode;
	if (key == 38 || key == 40 || key == 27)
	{
	    switch(key)
		{
        case 38: //omhoog
			this.gotoSuggestion(-1);
            break;
        case 40: //omlaag
			this.gotoSuggestion(1);
            break;
        case 27: //esc
			this.hide()
            break;
		}
    }
	else
	{
		if(this.popuptimeout != null)
		{
			clearTimeout(this.popuptimeout);
		}

//		this.data_changed();
//		this.popuptimeout = setTimeout(this.changed, 250);
		this.changed();
	}
}

AutoComplete.prototype.changed = function()
{
	var words = this.field.val();
	$.getJSON(this.url, { words: words }, this.callback);
}

AutoComplete.prototype.callback = function(data)
{
	this.data = data.words;
	this.data_changed();
}

AutoComplete.prototype.data_changed = function()
{
	this.popup.empty();

	var data = this.data;

//	var currentValue = this.field.val();
//	var data = $.grep(this.data, function(value)
//	{
//		return currentValue && value.substring(0, currentValue.length) == currentValue;
//	});

	if(data.length == 0)
	{
		this.hide();
		return;
	}

	for(var word in data)
	{
		var element = $('<div class="word">' + data[word] + '</div>');
		element.appendTo(this.popup);
	}

	this.popup.children().hover(this.onhover, function() {});
	this.popup.children().click(this.onclick);

	// show popup
	this.popup.slideDown();
	this.visible = true;
	this.gotoSuggestion(0, true);
}

AutoComplete.prototype.onhover = function(event)
{
	this.select(event.target);
}

AutoComplete.prototype.select = function(element)
{
	var children = this.popup.children();

	var index = -1;
	for(var i = 0; i < children.size(); i++)
	{
		if(children[i] == element)
		{
			index = i;
			break;
		}
	}

	this.gotoSuggestion(index, true);
}

AutoComplete.prototype.gotoSuggestion = function(index, absolute)
{
	if(absolute)
	{
		this.selected_index = index;
	}
	else
	{
		this.selected_index += index;
	}

	var children = this.popup.children();

	if(this.selected_index >= children.size())
	{
		this.selected_index = children.size() - 1;
	}
	if(this.selected_index < 0)
	{
		this.selected_index = 0;
	}

	children.removeClass('selected');
	this.getSelected().addClass('selected');
}

AutoComplete.prototype.onclick = function(event)
{
	this.select(event.target);
	this.completeword();
}

AutoComplete.prototype.completeword = function()
{
	var text = this.getSelected().text()+'';
	this.field.val(text);
	this.hide();
}

AutoComplete.prototype.getSelected = function()
{
	var children = this.popup.children();
	return $(children[this.selected_index]);
}

