jQuery.fn.extend({
	selectbox: function(options) {
		return this.each(function() {
			jQuery.SelectBox(this, options);
		});
	}
});

jQuery.SelectBox = function(selectobj, options) {
	var opt = options || {};
	opt.inputClass = opt.inputClass || "selectbox";
	opt.containerClass = opt.containerClass || "selectbox-wrapper";
	opt.buttonClass = opt.buttonClass || "selectButton";
	opt.buttonWrapperClass = opt.buttonWrapperClass || "selectButtonWrapper";
	opt.hoverClass = opt.hoverClass || "current";
	opt.currentClass = opt.selectedClass || "selected"

	var elm_id = selectobj.id;
	var isElementNew = ($("#" + elm_id + "_input").length == 0)
	var active = -1;
	var inFocus = false;
	var hasfocus = false;
	//jquery object for select element
	var $select = $(selectobj);
	// jquery container object
	var $container = setupContainer(opt);
	//jquery input object
	var $input = setupInput(opt);
	//jquery select button object
	var $selectButton = setupSelectButton(opt);
	//jquery select button wrapper object
	var $selectButtonWrapper = setupSelectButtonWrapper(opt);

	// hide select and append newly created elements
	$select.hide().before($selectButtonWrapper).before($container);
	
	init();
	
	$input.click(function(){
		if (!inFocus) {
			inFocus = !inFocus;
			$container.toggle();
		}
	});
	
	$selectButton.click(function(){
		if (!inFocus) {
			inFocus = !inFocus;
			$container.toggle();
		}
	});
	
	$input.focus(function(){
		inFocus = true;
		$container.show();
	});
	
	$input.keydown(function(event) {
		switch(event.keyCode) {
			case 38: // up
				event.preventDefault();
				moveSelect(-1);
				break;
			case 40: // down
				event.preventDefault();
				moveSelect(1);
				break;
			case 13: // return
				event.preventDefault();
				$('li.'+opt.hoverClass).trigger('click');
				break;
			case 27: //escape
				hideMe();
				break;
		}
	});

	$input.blur(function() {
		if(inFocus && !hasfocus) hideMe();	
	});

	$container.mouseout(function(event) {
		hasfocus = false;
	});

	$container.mouseover(function(event) {
		hasfocus = true;
	});
	
	function hideMe() {
		inFocus = false;
		hasfocus = false;
		$container.hide();
	}
	
	function init() {
		$container.hide();
		$container.empty();
		$container.append(getSelectOptions($input.attr('id')));
		$container.width($input.css('width'));
		
		$selectButtonWrapper.empty();
		$selectButtonWrapper.append($input);
		$selectButtonWrapper.append($selectButton);
    }

	function setupContainer(options) {
		var $container;
		if(isElementNew) {
			var container = document.createElement("div");
			$container = $(container);
			$container.attr('id', elm_id + "_container");
			$container.addClass(options.containerClass);
		} else {
			$container = $("#" + elm_id + "_container");
		}
		return $container;
	}

	function setupInput(options) {
		var $input;
		if(isElementNew) {
			var input = document.createElement("input");
			$input = $(input);
			$input.attr("id", elm_id + "_input");
			$input.attr("type", "text");
			$input.addClass(options.inputClass);
			$input.attr("autocomplete", "off");
			$input.attr("readonly", "readonly");
			$input.attr("tabIndex", $select.attr("tabindex"));
		} else {
			$input = $("#" + elm_id + "_input");
		}
		return $input;
	}
	
	function setupSelectButton(options) {
		var $selectButton;
		if(isElementNew) {
			var selectButton = document.createElement("div");
			$selectButton = $(selectButton);
			$selectButton.attr("id", elm_id + "_button");
			$selectButton.addClass(options.buttonClass);
		} else {
			$selectButton = $("#" + elm_id + "_button");
		}
		return $selectButton;
	}

	function setupSelectButtonWrapper(options) {
		var $selectButtonWrapper;
		if(isElementNew) {
			var selectButtonWrapper = document.createElement("div");
			$selectButtonWrapper = $(selectButtonWrapper);
			$selectButtonWrapper.attr("id", elm_id + "_buttonWrapper");
			$selectButtonWrapper.addClass(options.buttonWrapperClass);
		} else {
			$selectButtonWrapper = $("#" + elm_id + "_buttonWrapper");
		}
		return $selectButtonWrapper;
	}	
	
	function moveSelect(step) {
		var lis = $("li", $container);
		if (!lis) return;
		active += step;
		if (active < 0) {
			active = 0;
		} else if (active >= lis.size()) {
			active = lis.size() - 1;
		}
		lis.removeClass(opt.hoverClass);
		$(lis[active]).addClass(opt.hoverClass);
	}

	function setCurrent() {
		var li = $("li."+opt.currentClass, $container).get(0);
		var ar = (''+li.id).split('_');
		var el = ar[ar.length-1];
		$select.val(el);
		var tmpval = $(li).html();
		$input.val(tmpval);
		return true;
	}

	// select value
	function getCurrentSelected() {
		return $select.val();
	}

	// input value
	function getCurrentValue() {
		return $input.val();
	}

	function getSelectOptions(parentid) {
		var ul = document.createElement('ul');
		ul.setAttribute('id', parentid + '_ul');
		$select.children('option').each(function() {
			var li = document.createElement('li');
			li.setAttribute('id', parentid + '_' + $(this).val());
			li.innerHTML = $(this).html();
			if ($(this).is(':selected')) {
				$input.val($(this).html());
				$(li).addClass(opt.currentClass);
			}
			ul.appendChild(li);
			//Event Handlers
			$(li).click(function(event) {
				$('li.'+opt.currentClass).removeClass(opt.currentClass);
				$(this).addClass(opt.currentClass);
				setCurrent();
				hideMe();
				$select.change();
			});
			$(li).mouseover(function(event) {
				jQuery(event.target, $container).addClass(opt.hoverClass);
			});
			$(li).mouseout(function(event) {
				jQuery(event.target, $container).removeClass(opt.hoverClass);
			});
		});
		return ul;
	}
};