(function($){
	$.fn.jcomplete = function (options) {
		return $.jcomplete(this, options);
	};
	
	$.jcomplete = function (obj, options) {
		//OPTIONS
		var defaults = {
			highlightColor: '#DADADA',
			width: 225,
			height: 65,
			topOffset: 20,
			url: '',
			querystring: '',
			searchParam: '',
			depObjs: '',
			forceDep: false,
			idObject: '',
			jsonSetName: '',
			jsonElementID: '',
			jsonElementName: ''
		};
		var options = $.extend(defaults, options);
		
		if ( $('#jcompleteList').length == 0 ){
			$("body").append('<div id="jcompleteList" style="display:none;"></div>');
		};
		
		$("#jcompleteList").css({'text-align':'left'});
		
		//CHECK REQUIRED OPTIONS
		if ( options.url == '' || options.querystring == '' || options.searchParam == '' || options.jsonSetName == '' || options.jsonElementName == '' ){
			return false;
		}
		
		var timeoutID;
		var ENTER = 13;
		var TAB = 9;
		var SHIFT = 16;
		var ALT = 18;
		var ESC = 27;
		var LEFT = 37;
		var UP = 38;
		var RIGHT = 39;
		var DOWN = 40;
			
		$(obj).bind("keydown", function(e) {
			if ( e.which == ENTER || e.which == TAB ) {
				var selectedID = $("#jcompleteSelected").html();
				
				if ( selectedID != null && selectedID != '' && selectedID != -1 ){
					e.preventDefault();
					blockSubmit = true;

					if ( selectedID != null && selectedID != '' && selectedID != -1 ) {
						$(obj).val($("#jcomplete" + selectedID).html());
						if ( options.jsonElementID != '' && options.idObject != '' ) {
							$(options.idObject).val($("#jcompleteID" + selectedID).html());
						};
						$.jcomplete.close();
					};
					return false;
				};
			} else if ( e.which == SHIFT ){
				blockSubmit = true;
			};
		});
		/*
		$(obj).bind("keypress", function(e) {
			if ( e.keyCode == ENTER ) {
				e.preventDefault();
				blockSubmit = true;
				var selectedID = $("#jcompleteSelected").html();
				
				if ( e.keyCode == ENTER ){
					if ( selectedID != null ) {
						$(obj).val($("#jcomplete" + selectedID).html());
						if ( options.jsonElementID != '' && options.idObject != '' ) {
							$(options.idObject).val($("#jcompleteID" + selectedID).html());
						};
						$.jcomplete.close();
					};
				};
				return false;
			};
		});
		*/

		$(obj).bind("focus", function(e) {
			$(obj).attr("autoComplete", "off")
		});
		$(obj).bind("blur", function(e) {
			setTimeout( function() { $.jcomplete.close($(obj)) }, 300 );
		});
		
		$(obj).keyup(function(event){
			if ( event.keyCode == UP || event.keyCode == DOWN ) {
				var selectedID = $("#jcompleteSelected").html();
				var jcompleteLength = $("#jcompleteLength").html() - 1;
				
				if ( event.keyCode == UP ){
					if ( selectedID != -1 ){
						$("#jcomplete" + selectedID).css({'background-color':'#FFFFFF'});
					}
					selectedID--;
					if ( selectedID <= -1 ){
						//alert('test' + jcompleteLengths);
						selectedID = jcompleteLength;
						$("#jcompleteList").animate({scrollTop:15*(jcompleteLength-1)},'fast'); 
					};
					$("#jcompleteSelected").html(selectedID);
					$("#jcomplete" + selectedID).css({'background-color':options.highlightColor});
					if ( selectedID == jcompleteLength ){
						//do nothing;
					} else if ( selectedID > 2 ) {
						$("#jcompleteList").animate({scrollTop:$("#jcompleteList").scrollTop()-15},'fast');
					} else {
						$("#jcompleteList").animate({scrollTop:0},'fast');
					}
				} else {
					$("#jcomplete" + selectedID).css({'background-color':'#FFFFFF'});
					selectedID++;
					if ( selectedID > jcompleteLength ){ selectedID = 0 };
					$("#jcompleteSelected").html(selectedID);
					$("#jcomplete" + selectedID).css({'background-color':options.highlightColor});
					if ( selectedID > 2 ) {
						$("#jcompleteList").animate({scrollTop:$("#jcompleteList").scrollTop()+15},'fast');
					} else {
						$("#jcompleteList").animate({scrollTop:0},'fast');
					}
				}
			};
			
			if ( event.keyCode == ESC ){
				$.jcomplete.close();
			};
			
			if ( event.keyCode != ESC && event.keyCode != ENTER && event.keyCode != SHIFT && event.keyCode != TAB && event.keyCode != ALT && event.keyCode != LEFT && event.keyCode != UP && event.keyCode != RIGHT && event.keyCode != DOWN ) {
				//clear idObject
				if ( options.jsonElementID != '' && options.idObject != '' ) {
					$(options.idObject).val('');
				};
				if ( timeoutID != 'undefined' ) { clearTimeout(timeoutID) };
				timeoutID = setTimeout( function() { $.jcomplete.getResults($(obj), options) }, 250 );
			};
		});
	};

	$.jcomplete.getResults = function (obj, options){
		var pos = $(obj).position();
		var top = Math.round(pos.top);
		var left = Math.round(pos.left);
			
		//38 = up arrow
		//40 = down arrow
	
		//alert('jcomplete Name Changed -- Length: ' + $(obj).val().length);
		if ( $(obj).val().length > 0 ) {
			var showResults = true;
			var depVal = false;
			var datastring = options.querystring + "&" + options.searchParam + "=" + $(obj).val();
			//if ( options.depObjName != '' && options.depObjValName != '' ){
			//	datastring += "&" + options.depObjName + "=" + eval('$("#' + options.depObjValName + '").val()');
			//}
			if ( options.depObjs != '' ){
				if ( options.depObjs.deps.length > 0 ){
					$.each(options.depObjs.deps, function(i,elem){
						if ( elem.dobj.val() != '' ) {
							depVal = true;
							datastring += "&" + elem.dname + "=" + elem.dobj.val();
						};
					});
				};
			};
			if ( depVal == false && options.forceDep == true ){
				return;
			};
			datastring += "&random=" + Math.random();
			$("#jcompleteList").empty();
			$("#jcompleteList").hide();
			$.ajax({
				type: "GET",
				async: false,
				cache: false,
				contentType: "application/json; charset=utf-8",
				dataType: "json",
				url: options.url,
				data: datastring,
				success: function(json){
					if ( eval('json.'+options.jsonSetName+'.length') == 0 ){
						$("#jcompleteList").append('<span class="small gray">No Results Found</span><br/>')
						showResults = false;
					} else {
						$("#jcompleteList").append('<div id="jcompleteSelected" style="display:none;">-1</div><div id="jcompleteLength" style="display:none;">' + json.cities.length + '</div>');
						$.each(eval('json.'+options.jsonSetName), function(i,jsonElement){
							$("#jcompleteList").append('<div id="jcomplete' + i + '">' + eval('jsonElement.'+options.jsonElementName) + '</div>')
							if ( options.jsonElementID != '' && options.idObject != '' ) {
								$("#jcompleteList").append('<div id="jcompleteID' + i + '" style="display:none;">' + eval('jsonElement.'+options.jsonElementID) + '</div>')
							};
							if ( options.jsonElementID != '' && options.idObject != '' ) {
								$("#jcomplete" + i).bind("click", {name: eval('jsonElement.'+options.jsonElementName), id: eval('jsonElement.'+options.jsonElementID)}, function(e){
									$(options.idObject).val(e.data.id);
									$(obj).val(e.data.name);
									$.jcomplete.close()
								});
							} else {
								$("#jcomplete" + i).bind("click", {name: eval('jsonElement.'+options.jsonElementName)}, function(e){
									$(obj).val(e.data.name);
									$.jcomplete.close()
								});
							}
							$("#jcomplete" + i).css({'height':'15','cursor':'pointer','border-bottom':'solid 1px #FFFFFF'});
							$("#jcomplete" + i).mouseover(function(){
								$("#jcomplete" + $("#jcompleteSelected").html()).css({'background-color':'#FFFFFF'});
								$("#jcompleteSelected").html(i);
								$("#jcomplete" + i).css({'background-color':options.highlightColor});
							}).mouseout(function(){
								$("#jcomplete" + i).css({'background-color':'#FFFFFF'});
							});
						});
					};
				}
			});
			if ( showResults ){
				$("#jcompleteList").css({'background-color':'#FFFFFF','position':'absolute','border':'solid 1px #BABABA','overflow':'auto','width':options.width,'height':options.height,'z-index':'9000','top':top + options.topOffset,'left':left});
				$("#jcompleteList").show();
			};
		} else {
			$.jcomplete.close();
		};
	};
	
	$.jcomplete.close = function (obj) {
		$("#jcompleteList").empty();
		$("#jcompleteList").hide();
	};

})(jQuery);
