/**
 * selectInput
 * 
 * provide select elements with a "smarter" type-ahead
 * 
 * @version 0.1.7 2009-06-10
 * @author Gregor Kofler, info@gregorkofler.at
 * 
 * @param {object} elem select element
 * 
 * @todo minor issues when using effects on Opera
 * @todo check positioning with absolutely positioned containers
 */

if(!vxJS) { throw new Error("widget.selectInput: vxJS core missing."); }

vxJS.widget.selectInput = function(elem) {
	if(!elem) { throw new Error("widget.selectInput: Missing element."); }
	
	var	cancelNdx, input, layer, visible,
		that = {
			__show: function(elem) {
				elem.style.display = "";
				input.focus();
			},
			__hide: function(elem) {
				elem.style.display = "none";
			},
			__getElem: function() {
				return layer;
			},
			__fxChange: function(fx, from, to) {
				if(from === "sleeping" && to === "show") {
					vxJS.selection.setCaretPosition(input, "end");
				}
				if(from === "sleeping" && to === "hide") {
					input.value = "";
				}
			}
		};

	var chooseOption = function(t) {
		var o = elem.options, i, r = new RegExp("^"+t, "i");
		for(i = 0; i < o.length; i++) {
			if(r.test(vxJS.dom.concatText(o[i]))) {
				elem.selectedIndex = i;
				return;
			}
		}
	};

	var show = function() {
		var	s = vxJS.dom.getElementSize(elem),
			p = vxJS.dom.getElementOffset(elem);

		vxJS.dom.setElementPosition(layer, { x: p.x + 8, y: p.y + s.y - 8 });
		input.value = "";
		that.__show(layer);
		visible = true;
	};

	var hide = function() {
		that.__hide(layer);
		visible = false;
		elem.focus();
	};

	var selectKeyDown = function(e) {
		var kc = e.keyCode;

		if(!visible && (kc === 32 || kc > 45 && kc < 112 || kc > 123)) {
			cancelNdx  = elem.selectedIndex || 0;
			show();
		}
	};
	
	var selectKeyPress = function(e) {
		if(visible) {
			input.value = String.fromCharCode(e.keyCode || e.charCode);
			chooseOption(input.value);
		}
	};

	var inputKeyDown = function(e) {
		var kc = e.keyCode;

		if(kc !== 27 && kc !== 13 && kc !== 38 && kc !== 40) {
			return;
		}
		switch(kc) {
			case 27:
				elem.selectedIndex = cancelNdx;
				break;
			case 13:
				vxJS.event.preventDefault(e);
		}
		vxJS.event.fireEvent(input, "blur");
	};

	var inputKeyUp = function(e) {
		var kc = e.keyCode;

		if (kc < 32 && kc != 8 || (kc >= 33 && kc < 46) || (kc >= 112 && kc <= 123)) {
			return;
		}
		chooseOption(input.value);
	};

	layer = "span".setProp("class", "vxJS_selectInput").create((input = "input".create()));
	layer.style.position = "absolute";
	layer.style.display = "none";

	document.body.insertBefore(layer, document.body.lastChild.nextSibling);

	vxJS.event.addListener(elem, "keydown", function(e) {
		selectKeyDown(e);
	});
	vxJS.event.addListener(elem, "keypress", function(e) {
		selectKeyPress(e);
	});
	vxJS.event.addListener(input, "blur", function(e) {
		hide();
	});
	vxJS.event.addListener(input, "keyup", function(e) {
		inputKeyUp(e);
	});
	vxJS.event.addListener(input, "keydown", function(e) {
		inputKeyDown(e);
	});
	
	return that;
};