var MysticMeg = new Class({
	initialize: function(element, options){
		this.setOptions({
			ajaxUrl: window.location.pathname,
			autoStyle: true,
			listClass: "MysticMeg",
			highlight: true,
			multipleSelect: true,
			delay: 500,
			onSelect: Class.empty,
			onSuccess: Class.empty,
			topOffset: 0,
			leftOffset: 0
		}, options);
		
		this.element = element;
		
		this.totalItems = 0;
		this.selectedItem = -1;
		
		this.clearAjaxTimer = 0;
		this.periodicalAjaxTimer = 0;
		this.displayTimer = 0;
		
		if($type($(element)) == "element" && $(element).getTag() == "input") {
			$(element).setProperty("autocomplete", "off");
			$(element).addEvents({
				"focus": (function(){
					if(this.options.multipleSelect)
						this.getResults();
				}).bind(this),
				"keydown": (function(event){
					var e = new Event(event);

					if(e.shift && e.key == "tab"){
						this.hideResults();
						return;
					}

					if(e.shift || e.control || e.alt){
						return;
					}

					switch(e.key) {
						case 'enter':
							e.stop();
							if(this.totalItems > 0 && this.selectedItem >= 0)
								($(this.listID).getElements("a")[this.selectedItem]).fireEvent("click", e);
							return;
						case 'up': 
							var currentlySelected = this.selectedItem;
							this.selectItem(--currentlySelected);
							e.stop(); 
							return;
						case 'down':
							var currentlySelected = this.selectedItem;
							this.selectItem(++currentlySelected);
							e.stop(); 
							return;
						case 'esc', 'tab':
							this.hideResults();
							return;							
					}
				
					$clear(this.clearAjaxTimer);
					this.clearAjaxTimer = 0;
					if(this.periodicalAjaxTimer == 0) 
						this.periodicalAjaxTimer = (function(){ 
							this.getResults();
						}).periodical(this.options.delay, this);
				}).bindWithEvent(this),
				"keyup": (function(){
					if(this.clearAjaxTimer == 0) {
						this.clearAjaxTimer = (function(){ 
							$clear(this.periodicalAjaxTimer);
							this.periodicalAjaxTimer = 0;
							//this.getResults();
						}).delay(this.options.delay, this);
					}
				}).bind(this)
			});
			this.dimensions = $(element).getSize();
			this.listID = $pick($(element).getProperty("id"), "MysticMeg-") + Date.parse(new Date());
			this.draw();
		}

	},
	
	draw: function() {
		var listContainer = new Element("div",{
			"id": this.listID,
			"class": this.options.listClass/*,
			"events": {
				"mouseover": (function(){
					$clear(this.displayTimer); 
				}).bind(this),
				"mouseout": (function(){ 
					this.displayTimer = (function(){ $(this.listID).setStyle("display", "none"); }).delay(500, this);
				}).bind(this)
			}*/
		});
		
		$(document.body).addEvent("click", this.hideResults.bind(this));
		
		this.listContainer = listContainer;
		
		if(this.options.autoStyle) {
			listContainer.setStyles({
				"display": "none",
				"position": "absolute",
				"left": $(this.element).getLeft() + this.options.leftOffset,
				"top": $(this.element).getTop() + this.options.topOffset
			});
		}
		
		listContainer.injectInside(document.body);
		new Element("ul",{
			"id": this.listID + "-List"
		}).injectInside(listContainer);
	},
	
	flush: function() {
		$(this.listID + "-List").empty();
	},
	
	getResults: function() {
		var preText = $(this.element).getValue();
		if(preText == "") {
			this.displayResults([]);
		} else {
			new Ajax(this.options.ajaxUrl,{
				method: "get",
				postBody: "requestType=ajax&action=autoComplete&keywords=" + preText + "&autoCompleteID=" + $(this.element).getProperty("id"),
				onComplete: (function(response){
					this.displayResults(Json.evaluate(response));
				}).bind(this),
				onFailure: (function(){
					this.displayResults([]);
				}).bind(this)
			}).request();
		}
	},
	
	displayResults: function(objResultSet) {
		this.totalItems = objResultSet.length;
		this.selectedItem = -1;
		if(this.options.autoStyle) {
			this.listContainer.setStyles({
				"left": $(this.element).getLeft() + this.options.leftOffset,
				"top": $(this.element).getTop() + this.options.topOffset
			});
		}
		this.flush();
		if(objResultSet.length == 0) {
			$(this.listID).setStyle("display","none");
		} else {
			$(this.listID).setStyle("display","block");
		}
		$each(objResultSet, function(o, index){
			var anchor = new Element("a",{ 
				"href": "#item" + index,
				"events": {
					"click": (function(e, selectedObj){ 
						new Event(e).stop();
						this.options.onSelect(selectedObj, this.element, this);
					}).bindWithEvent(this, objResultSet[index])
				}
			});
			if(this.options.highlight){
				var highlightText = $(this.element).getValue();
				var highlightSpan = "<span class='highlight'>" + highlightText + "</span>";
				var pattern = RegExp(highlightText, "gi");
				new Element("span").setHTML(o.value.replace(pattern, highlightSpan)).injectInside(anchor);
			} else {
				anchor.setText(o.value);
			}
			anchor.injectInside(new Element("li").injectInside($(this.listID + "-List")));
		}, this);
		
		var windowSize = window.getSize();
		var listSize = $(this.listID).getSize();
		var window_y = windowSize.size.y + windowSize.scroll.y;
		var list_y = $(this.listID).getTop() + listSize.size.y;
		if(window_y < list_y) {
			var resizeBy = list_y - window_y;
			$(this.listID).setStyles({
				"height": listSize.size.y - resizeBy,
				"overflow": "scroll"
			});
		} else {
			$(this.listID).setStyles({
				"height": "auto",
				"overflow": "visible"
			});
		}
			
		this.options.onSuccess(objResultSet, this.element);
	},
	
	hideResults: function() {
		$(this.listID).setStyle("display","none");
	},
	
	selectItem: function(index) {
		
		if(this.totalItems == 0) return;
		
		if(index < 0)
			index = this.totalItems - 1;
		if(index >= this.totalItems)
			index = 0;
		
		var anchors = $(this.listID).getElements("a");
		if(this.selectedItem >= 0) (anchors[this.selectedItem]).removeClass("selected");
		(anchors[index]).addClass("selected");
		this.selectedItem = index;
	}
});

MysticMeg.implement(new Options);
