/**
 * This object is designed to trigger a callback function when the user stops typing
 *
 * To use this construct, use the following syntax:
 * onkeyup="OnKeyStop.Do(keyStopEvent)"
 *
 * where "keyStopEvent" is the name of the JavaScript callback function that will be executed.
 * one second after the user stops typing. The callback function must be defined by you.
 */
function KeyStopTimer(wait)
{
	if(typeof wait == 'undefined')
		wait = 1000;

	this.interval = wait;
	this.timer = null;
}

KeyStopTimer.prototype.Do = function(eventCallback) {
	this.Cancel();
	this.timer = setTimeout(function() {
		eventCallback();
	}, this.interval);
}

KeyStopTimer.prototype.Cancel = function() {
	if(this.timer != null)
		clearTimeout(this.timer);
}

OnKeyStop = new KeyStopTimer();


function AutoComplete(id, forceSelection, err_msg)
{
	if(typeof forceSelection == 'undefined')
		forceSelection = 0;
	if(typeof err_msg == 'undefined')
		err_msg = '';

	this.frc = forceSelection;
	this.err_msg = err_msg;
	this.id = id;
	this.elem = $(this.id);
	this.obj = 'auto_'+id;
	this.remote = null;
	this.extra = null;
	this.lit = null;
	this.res = null;
	this.data = new Array();
	this.calls = 0;
	this.text_change = 0;

	this.blur_timer = new KeyStopTimer(250);
	this.myStop = new KeyStopTimer(250);

	var that = this;
	this.elem.observe('keyup', function(event){
		switch(that.get_key(event))
		{
			default:
				that.text_change = 1;
			case Event.KEY_TAB:
			case Event.KEY_RETURN:
			case Event.KEY_UP:
			case Event.KEY_DOWN:
			case Event.KEY_LEFT:
			case Event.KEY_RIGHT:
			case Event.KEY_ESC:
				break;
		}
		that._keyup(event);
	});

	// Tab has to be captured onkeydown, or the browser takes over
	this.elem.observe('keydown', function(event){
		if(that.get_key(event) == Event.KEY_TAB)
		{
			that.key_nav(Event.KEY_TAB);
			event.stop();
		}
	});

	this.elem.observe('blur', function(event){
		that.blur_timer.Do(function(){
			that.clear();
		});
	});
}

AutoComplete.prototype.force_selection = function(){
	if(this.frc)
	{
		var val = this.elem.value.toLowerCase(),
			match = 0;
		for(var i=0;i<this.data.length;i++)
		{
			if(this.data[i].toLowerCase() == val)
			{
				this.elem.value = this.data[i];
				match = 1;
				break;
			}
			else // take the first value in the list
			{
				if(this.data[0])
				{
					this.elem.value = this.data[0];
					match = 1;
				}
			}
		}

		if(!match)
			this.show_error();
	}
}

AutoComplete.prototype.show_error = function(){
	this.elem.value = this.err_msg;
}

AutoComplete.prototype.set_extra = function(key, val){
	this.data = new Array();
	var ex = new Hash();
	if(this.extra != null)
		ex = $H(eval('('+this.extra+')'));

	ex.set(key, val);
	this.extra = ex.toJSON();
}

AutoComplete.prototype.get_key = function(event){
	return (event.keyCode)?event.keyCode:((event.which)?event.which:event.charCode);
}

AutoComplete.prototype.move = function(adj){
	var elem = null;
	if(this.lit != null)
	{
		if(adj < 0)
			elem = this.lit.previous();
		else
			elem = this.lit.next();
	}
	else
		elem = this.res.down();

	if(elem)
	{
		this.highlight(elem);
		var pos = this.lit.positionedOffset(),
			height = this.res.getHeight();
		this.res.scrollTop = pos[1] - height + this.lit.getHeight();
	}
}

AutoComplete.prototype.highlight = function(elem){
	if(this.lit)
		this.lit.removeClassName('highlight_row');
	this.lit = elem;
	this.lit.addClassName('highlight_row');
}

AutoComplete.prototype.key_nav = function(key){
	var b = 0;

	switch(key)
	{
		case Event.KEY_DOWN:
			this.move(1);
			break;

		case Event.KEY_UP:
			this.move(-1);

		case Event.KEY_RIGHT:
		case Event.KEY_LEFT:
			break;

		case Event.KEY_TAB:
			if(this.lit == null)
				this.lit = this.res.down();

		case Event.KEY_RETURN:
			if (this.calls > 0 || this.text_change)
			{
				var timer = new KeyStopTimer(100),
					that = this;
				timer.Do(function(){
					that.key_nav(Event.KEY_RETURN);
				});
				return 1;
			}

			if(this.lit)
				this.elem.value = this.lit.innerHTML;

			this.force_selection();
			this.elem.focus();

		case Event.KEY_ESC:
			this.clear();
			break;

		default:
			b = 1;
			break;
	}

	return b;
}

AutoComplete.prototype.clear = function(){
	if(this.res)
	{
		this.res.update('');
		this.res.hide();
		this.lit = null;
	}
}

AutoComplete.prototype.keyup = function(event){
	return this.key_nav(this.get_key(event));
}

AutoComplete.prototype._keyup = function(event)
{
	var b = this.elem.value != '';
	if(this.keyup(event) && b)
		this.ajax();
	else if(!b)
	{
		this.clear();
		this.text_change = 0;
	}
}

AutoComplete.prototype.ajax = function(disp)
{
	if(typeof disp == 'undefined')
		disp = true;

	var that = this;
	var opts = {
		method : 'post',
		parameters : {
			'query' : this.elem.value,
			'extra' : this.extra
		},
		onSuccess : function(trans){
						var resp=-1;
						try{resp = trans.responseText.evalJSON() || 'No response detected.'}
						catch(e){that._error(e)}
						if(that.elem.value == '')
							disp = false;
						that._success(resp, disp);
					},
		onFailure : function(trans){
						that._failure(trans);
					},
		onComplete : function(){that.calls--}
	};

	this.myStop.Do(function(){
		new Ajax.Request(that.remote, opts);
		that.calls++;
		that.text_change = 0;
	});
}

AutoComplete.prototype.success = function(resp){return resp}
AutoComplete.prototype._success = function(resp, disp)
{
	if(this.res)
		this.clear();
	else
	{
		var pos = this.elem.cumulativeOffset();
		this.res = new Element('div');
		this.res.className = 'auto_tooltip';
		this.res.style.width = (this.elem.getWidth()-5)+'px';
		this.res.style.left = pos.left+'px';
		this.res.style.top = pos.top + this.elem.getHeight()+'px';
		this.elem.up('body').insert(this.res)
	}

	var that = this;
	this.data = this.success(resp);
	if(this.data.length)
	{
		this.data.each(function(item){
			var div = new Element('div').insert(item);
			div.addClassName('clickable');
			that.res.insert(div);
			div.observe('mouseover', function(event){
				that.highlight(event.element());
			});
			div.observe('click', function(event){
				that.key_nav(Event.KEY_RETURN);
				that.blur_timer.Cancel();
			});
		});

		if(disp)
			this.res.show();
		else
			this.res.hide();
	}
	else
		this.res.hide();
}

AutoComplete.prototype.failure = function(trans){}
AutoComplete.prototype._failure = function(trans)
{
	this.failure(trans);
}

AutoComplete.prototype.error = function(ex){}
AutoComplete.prototype._error = function(ex)
{
	this.error(ex);
}

function handle_auto_submit(obj, allow_blank){
	if(typeof allow_blank == 'undefined')
		allow_blank = false;

	if(!obj.lit && !obj.calls && !obj.text_change)
	{
		if(!allow_blank || obj.elem.value!='')
			obj.force_selection();
		if(obj.elem.value != obj.err_msg)
			try{obj.elem.up('form').submit()}catch(e){}
	}
}


function clear_on(elem)
{
	for(var i=1;i<arguments.length;i++)
		if(elem.value == arguments[i])
			elem.value = '';
}

function show_loading(div, img)
{
	div.update('<div class="outer_shell"><div class="creamy_center"><img src="'+BASE_URL+'/home/images/'+img+'" /></div></div>');
}