
//remember to wait until after the window.load event has fired to make sure the css and images have loaded
jQuery.fn.ecglivesearch = function(module, options) {
	settings = jQuery.extend({
		fetch: null, //do we pass any extra data in the request (this is null or a function)
		afterReturn: null, //do we have a function to fire after the data has returned?
		alwaysRefresh: true
	}, options);
	
	var moveChoice = function(obj,direction,results){
		if(!obj.data('hasResults')){
			return false;
		}
		
		var objs = results.find('ul li.active');
		if(objs.length == 0){
			//none are selected
			setChoice(obj,results,results.find('ul li:first'));
		} else {
			if(direction>0){
				var next = objs.next();
				if(next.length>0){
					setChoice(obj,results,next);
				}
			} else {
				var prev = objs.prev();
				if(prev.length>0){
					setChoice(obj,results,prev);
				}
			}
		}
	}
	
	var setChoice = function(obj,results,li){
		results.find('ul li').removeClass('active');
		li.addClass('active');
	}
	
	var fadeSoon = function(tobj,now){
		var oldTimer = tobj.data('hide');
		if(oldTimer){
			window.clearTimeout(oldTimer);
		}
		var delay = 1000;
		if(now){
			delay = 0;
		}
		
		//this object is already hidden
		if(tobj.css('display') == 'none'){
			return false;
		}
		
		var timer = window.setTimeout(function(){
			tobj.fadeOut(250);
			tobj.removeData('hasResults');
		},delay);
		tobj.data('hide',timer);
	}
	
	var handleResult = function(obj,result,elem){		
		//wipe out the previous data
		elem.html('');
		
		if(result != null && result['data'] != null){
			var ul = $(document.createElement('ul'));
			var first = true;
			
			var key = result['data']['key'];
			var label = result['data']['label'];
			var data = result['data'][key];
			
			for(i in data){
				obj.data('hasResults',true);
				var li = $(document.createElement('li')).data('lsId',i).html(data[i][label]);
				ul.append(li);
				if(first && obj.val().length > 0){
					var cur = obj.val();
					var len = cur.length;
					var name = data[i][label];
					
					var objRaw = obj.get(0);
					
					if(objRaw.setSelectionRange){
						
						if(module != 'Program'){
							obj.val(name);
						}
						objRaw.setSelectionRange(len,name.length);
					} else if(objRaw.createTextRange){
						obj.val(name);
						var range = objRaw.createTextRange();
						range.moveStart("character",len);
						range.moveEnd("character", name.length);
						range.select();
					}
				}
				first = false;
			}
			
		} else {
			if(result == null || result['error']){
				if(result['msg']){
					elem.html(result['msg']);
				} else {
					elem.html("Unable to search right now, please try again later.");
				}
			}
		}
		
		var width = obj.outerWidth({ margin: true });
		var height = obj.outerHeight({ margin: true });
		var pos = obj.offset({ border: true, padding: true });
		
		var relativeParent = obj.offsetParent();
		var parentPos = relativeParent.offset({ border: true, padding: true });
		
		var top = pos['top'] + height - parentPos['top'];
		var left = pos['left']  - parentPos['left'];
		
		elem.css({top:top+'px',left:left+'px'});
		elem.append(ul).fadeIn(250);
		
		elem.hover(
			function(){
				var timer = $(elem).data('hide');
				if(timer){
					window.clearTimeout(timer);
				}
			},
			function(){
				fadeSoon($(elem));
			}
		);
		
		elem.find('li').hover(
			function(){
				setChoice(obj,elem,$(this));
			},function(){}
		).click(function(){
			obj.val($(this).html());
			obj.select();
			fadeSoon($(elem),true);
		});
	}
	
	return this.each(function(){
		var obj = $(this);
		
		obj.attr('autocomplete','off');
		
		obj.addClass('livesearch');
		
		var relativeParent = obj.offsetParent();
		
		if(relativeParent.get(0) == $('body').get(0)){
		}
		
		var width = obj.outerWidth({ margin: true, border: true, padding: true });
		var pos = obj.offset({ margin: true, border: true, padding: true });
		var parentPos = relativeParent.offset({ border: true, padding: true });
		
		var top = pos['top'] - parentPos['top'];
		var left = (width+pos['left']-parentPos['left'])-17;
		
		//make an adjustment so it's more pixel perfect with this class
		if(obj.hasClass('livesearch_on_tan')){
			top += 1;
			left += 1;
		}
		
		//we'll add the button next to the input area
		var arrow = $(document.createElement('div')).addClass('livesearch_button');
		var results = $(document.createElement('div')).addClass('livesearch_results');
		
		arrow.css({position:'absolute',top:top+'px',left:left+'px'});
		obj.after(arrow,results);
		
		arrow.click(function(){
			var val = obj.val();
			
			//send off this request if it's different from the last request
			if(settings.alwaysRefresh || val != obj.data('oldval')){
				
				if(settings.fetch != null){
					data = settings.fetch(obj);
				} else {
					data = {};
				}
				
				data['c'] = 'livesearch';
				data['module'] = module;
				
				$.getJSON('/widgets/api.php',data,function(result){handleResult(obj,result,results)});
				
				obj.data('oldval',val);
			}
			
			obj.removeData('timer');
		});
		
		obj.keyup(function(e){
			//set a timeout so we don't keep firing the event
			if((e.keyCode >= 48 && e.keyCode <= 90) || e.keyCode == 32 || !obj.data('hasResults')){
				if(obj.data('timer') != null){
					window.clearTimeout(obj.data('timer'));
				}
				obj.data('timer',window.setTimeout(function(){arrow.click();},250));
			}
		});
		
		obj.keydown(function(e){
			switch(e.keyCode){
				case 38: //up
					moveChoice(obj,-1,results);
					break;
				case 40: //down
					moveChoice(obj,1,results);
					break;
				case 39: //right
				case 13: //enter
					if(obj.data('hasResults')){
						var li = results.find('ul li.active');
						obj.val(li.html());
						fadeSoon(results,true);
					}
					break;
			}
		});
		
		obj.blur(function(){fadeSoon(results)});
	});
}
