// blank line needed for js concatenation
var SearchInPlace = Class.create({
	searchDelay: 1000,
	resultsId: 'searchInPlaceResults',

	initialize: function(searchBox)
	{
		if (!searchBox)
			searchBox = 'search';
		this.input = $(searchBox);
		if (!this.input)
			throw 'cannot find search box: "' + searchBox + '"';
		this.defaultValue = this.input.value;
		Event.observe(this.input, 'focus', this.focus.bind(this));
		Event.observe(this.input, 'blur', this.blur.bind(this));
		if (Element.hasClassName(this.input, 'search-in-place'))
			Event.observe(this.input, 'keyup', this.keyup.bindAsEventListener(this));
	},

	focus: function()
	{
		Element.addClassName(this.input, 'focused');
		if (this.input.value == this.defaultValue)
			this.input.value = '';
	},

	blur: function()
	{
		this.cancelSearch();
		window.setTimeout(this.hideResults.bind(this), 5);
		Element.removeClassName(this.input, 'focused');
		if (this.input.value == '')
			this.input.value = this.defaultValue;
	},

	keyup: function(event)
	{
		switch (event.keyCode)
				{
			case Event.KEY_UP:
				this.selectPrevious();
				break;
			case Event.KEY_DOWN:
				this.selectNext();
				break;
			case Event.KEY_RETURN:
				var selected = this.getSelected();
				if (selected)
					this.launch(selected.id);
				break;
			default:
				this.cancelSearch();
				this.timer = window.setTimeout(this.search.bind(this), this.searchDelay);
				break;
		}
		Event.stop(event);
	},

	getSelected: function()
	{
		return this.selectedIndex == null || !this.items ? null : this.items[this.selectedIndex];
	},

	selectNext: function()
	{
		if (this.items && this.items.length > 0)
		{
			if (this.selectedIndex == null)
			{
				this.selectedIndex = 0;
				Element.addClassName(this.items[this.selectedIndex], 'selected');
			}
			else
			{
				Element.removeClassName(this.items[this.selectedIndex], 'selected');
				this.selectedIndex = (this.selectedIndex + 1) % this.items.length;
				Element.addClassName(this.items[this.selectedIndex], 'selected');
			}
		}
	},

	selectPrevious: function()
	{
		if (this.items && this.items.length > 0)
		{
			if (this.selectedIndex == null)
			{
				this.selectedIndex = this.items.length - 1;
				Element.addClassName(this.items[this.selectedIndex], 'selected');
			}
			else if (this.selectedIndex == 0)
			{
				Element.removeClassName(this.items[this.selectedIndex], 'selected');
				this.selectedIndex = null;
			}
			else if (this.selectedIndex - 1 >= 0)
				{
					Element.removeClassName(this.items[this.selectedIndex], 'selected');
					this.selectedIndex--;
					Element.addClassName(this.items[this.selectedIndex], 'selected');
				}
		}
	},

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

	hideResults: function()
	{
		var results = $(this.resultsId);
		if (results)
			Element.remove(results);
	},

	launch: function(url)
	{
		if (url == 'showAll')
			$('quickSearch').submit();
		else
			document.location = url;
	},

	search: function()
	{
		var query = this.input.value;
		if (query && query.length > 0)
		{
			new Ajax.Request('/searchInPlace',
			{
				parameters: $H({q:query}).toQueryString(),
				onSuccess: function(transport)
				{
					this.hideResults();
					new Insertion.After(this.input, transport.responseText);
					var results = $(this.resultsId);
					this.items = results.select('selectable');
					this.selectedIndex = null;
					this.items.each(function(item, index)
					{
						Event.observe(item, 'mouseover', function()
						{
							if (index != this.selectedIndex)
							{
								if (this.selectedIndex != null)
									Element.removeClassName(this.items[this.selectedIndex], 'selected');
								this.selectedIndex = index;
								Element.addClassName(this.items[this.selectedIndex], 'selected');
							}
						}.bind(this));
						Event.observe(item, 'mousedown', function()
						{
							this.launch(item.id);
						}.bind(this));
					}.bind(this));
				}.bind(this)
			});
		}
	}
});
