Ajax.Search = Class.create();
Object.extend(Object.extend(Ajax.Search.prototype, Autocompleter.Base.prototype), {

	 baseInitialize: function(element, update, options) {
		element          = $(element)
		this.element     = element;
		this.update      = $(update);
		this.hasFocus    = false;
		this.changed     = false;
		this.active      = false;
		this.index       = -1;
		this.entryCount  = 0;

		if(this.setOptions)
			this.setOptions(options);
		else
			this.options = options || {};

		this.options.paramName    = this.options.paramName || this.element.name;
		this.options.tokens       = this.options.tokens || [];
		this.options.frequency    = this.options.frequency || 0.4;
		this.options.minChars     = this.options.minChars || 1;
		this.options.onShow       = this.options.onShow ||
		function(element, update){

			/*
			if(!update.style.position || update.style.position=='absolute') {
				update.style.position = 'absolute';
				Position.clone(element, update, {
					setHeight: false,
					offsetTop: element.offsetHeight
				});
			}
			*/

			Effect.Appear(update,{duration:0.15});
		};

		this.options.onHide = this.options.onHide || function(element, update){ new Effect.Fade(update,{duration:0.15}) };

		if(typeof(this.options.tokens) == 'string')
		this.options.tokens = new Array(this.options.tokens);

		this.observer = null;

		this.element.setAttribute('autocomplete','off');

		Element.hide(this.update);

		Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
		Event.observe(this.element, 'keypress', this.onKeyPress.bindAsEventListener(this));

		// Turn autocomplete back on when the user leaves the page, so that the
		// field's value will be remembered on Mozilla-based browsers.
		Event.observe(window, 'beforeunload', function(){
			element.setAttribute('autocomplete', 'on');
		});
  	},

	initialize: function(element, update, url, options) {
		this.baseInitialize(element, update, options);
		this.options.asynchronous	= true;
		this.options.onSuccess		= this.onSuccess.bind(this);
		this.options.defaultParams	= this.options.parameters || null;
		this.url			= url;
	},

	onKeyPress: function(event) {
		switch(event.keyCode) {
			case Event.KEY_TAB:
				if( !this.active ) return;
				this.hide();
				this.active = false;
				return;
			case Event.KEY_RETURN:
				if( !this.active ) return;
				this.selectEntry();
				this.hide();
				Event.stop(event);
				return;
			case Event.KEY_ESC:
				if( !this.active ) return;
				this.hide();
				this.active = false;
				Event.stop(event);
				return;
			case Event.KEY_LEFT:
			case Event.KEY_RIGHT:
				return;
			case Event.KEY_UP:
				if( !this.active ) return;
				this.markPrevious();
				this.render();
				this.updateElement(this.getCurrentEntry());
				Event.stop(event);
				return;
			case Event.KEY_DOWN:
				if( !this.active ) return;
				this.markNext();
				this.render();
				this.updateElement(this.getCurrentEntry());
				Event.stop(event);
				return;
			default:
				this.setObserver();
		}
		return;
	},

	setObserver: function() {
		if( ( Prototype.Browser.WebKit > 0 && event.keyCode == 0 ) ) return;

		this.changed = true;
		this.hasFocus = true;

		if(this.observer) clearTimeout(this.observer);
		this.observer =	setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
	},

	getUpdatedChoices: function() {
		this.startIndicator();

		var entry = encodeURIComponent(this.options.paramName) + '=' +
		encodeURIComponent(this.getToken());

		this.options.parameters = this.options.callback ?
		this.options.callback(this.element, entry) : entry;

		if(this.options.defaultParams)
		this.options.parameters += '&' + this.options.defaultParams;

		new Ajax.Request(this.url, this.options);
	},

	onSuccess: function(transport) {
		this.updateChoices( transport.responseText.evalJSON(true) );
	},

	updateChoices: function( choices ) {
		if(!this.changed && this.hasFocus) {
			var newhtml = '';
			for(i=0; i<choices.length; i++) {
				newhtml += '<li class="autocomplete">' + choices[i] + '</li>';
			}
			this.update.innerHTML = '<ul class="autocompleter">' + newhtml + '</ul>';
			Element.cleanWhitespace(this.update);
			Element.cleanWhitespace(this.update.down());

			if(this.update.firstChild && this.update.down().childNodes) {
				this.entryCount = this.update.down().childNodes.length;
				for (var i = 0; i < this.entryCount; i++) {
					var entry = this.getEntry(i);
					entry.autocompleteIndex = i;
					this.addObservers(entry);
				}
			}
			else {
				this.entryCount = 0;
			}

			this.stopIndicator();
			this.index = 0;

			if(this.entryCount==1 && this.options.autoSelect) {
				this.selectEntry();
				this.hide();
			}
			else {
				this.render();
			}
		}
	}
});
