/**
 * QueryPopup
 * 
 * value of an input element is forwarded to an AJAX request
 * a popup with the server reply is displayed
 * selection of a value sets values of input element and optional key element
 * @version 2.5.0 2009-06-23
 *
 * @param {Object}	button element that triggers popup
 * @param {Object}	xhr request command and URI
 * @param {String}	optional init text of popup search field
 * @param {Object}	optional element used instead of popup search field
 * @param {Object}	optional message texts { standard: ..., wait: ... }
 * 
 * served events: "select", "show", "hide"
 * 
 */
/*global document, vxJS */

if(!vxJS || !vxJS.xhr || !vxJS.widget) { throw Error("widget.queryPopup: vxJS core or vxJS.xhr or vxJS.widget missing."); }

vxJS.widget.queryPopup = function(button, xhrReq, initText, sElement, messages) {
	var	that = {}, xhr, list = vxJS.widget.shared.list(), hidden = true,
		layer, searchInput, msgBox = "div".setProp("class", "vxJS_queryPopupInfo").create(""),
		xhrImg, xhrImgSize;

	xhrImg = function() {
		var i = "img".setProp("src", "js/xhr_activity.gif").create();
		i.style.position = "absolute";
		vxJS.dom.setElementPosition(i, { x: -100, y: -100 } );
		return i;
	}();

	var showMsgBox = function(msg) {
		if(!msg) {
			msgBox.style.display = "none";
			return;
		}
		vxJS.dom.deleteChildNodes(msgBox);
		msgBox.appendChild(msg.nodeType ? msg : document.createTextNode(msg || ""));
		msgBox.style.display = "";
	};

	var	show = function () {
		if(hidden) {
			vxJS.dom.setElementPosition(layer, vxJS.dom.getElementOffset(button));
			that.show();
			vxJS.event.serve(that, "show");
			if(searchInput) {
				searchInput.focus();
			}
			hidden = false;
		}
	};

	var hide = function() {
		if(xhr) {
			xhr.abort();
		}
		that.hide();
		vxJS.event.serve(that, "hide");
		hidden = true;
	};

	var handleXhrResponse = function(r) {
		r = r || {};

		showMsgBox(r.message ? vxJS.dom.parse(r.message) : (!r.entries || !r.entries.length ? messages.notFound : null));

		if(!r.entries || !r.entries.length) { return; }

		list.fill(r.entries);

		if(r.hiLite && vxJS.widget.shared.hiLite) {
			vxJS.widget.shared.hiLite(r.hiLite, list.element);
		}
		if(sElement) {
			show();
		}
		list.focus();
	};

	var submit = function(txt) {
		var p, s;
		if(!sElement) {
			showMsgBox(messages.wait);
		}

		if(!xhrImgSize && xhrImg.complete) {
			xhrImgSize = vxJS.dom.getElementSize(xhrImg);
		}
		if(xhrImgSize) {
			p = vxJS.dom.getElementOffset(sElement || searchInput);
			s = vxJS.dom.getElementSize(sElement || searchInput);
			p.x += s.x-xhrImgSize.x-4;
			p.y += (s.y-xhrImgSize.y)/2;
			vxJS.dom.setElementPosition(xhrImg, p);
		}

		if(xhr) {
			xhr.use(null, null, { text: txt }, { node: xhrImgSize ? xhrImg : null });
			return;
		}
		xhr = vxJS.xhr(xhrReq,
				{ completed: handleXhrResponse },
				{ text: txt },
				{ node: xhrImgSize ? xhrImg : null }
		);	
	};

	var buttonListener = function(e) {
		var init = {};

		vxJS.event.cancelBubbling(e);
		
		if (sElement) {
			submit(sElement.value.trim());
			return;
		}
		searchInput.value = init.initValue || initText;
		showMsgBox(messages.standard);
		list.fill([]);
		show();
		vxJS.selection.set(searchInput);
	};

	/**
	 * initialize and create widget
	 */

	if(!sElement || !sElement.nodeName || !sElement.nodeName === "INPUT") {
		sElement = null;
	}

	initText = initText || "";
	messages = messages || {
		standard: "Bitte geben Sie einen Suchbegriff ein.",
		wait: "Bitte warten...",
		notFound: "Keine Ergebnisse gefunden!"
	};
	
	xhrReq = xhrReq || {};

	layer = "div".setProp("class", "vxJS_queryPopup").create();
	layer.style.position = "absolute";
	layer.style.display = "none";

	if(!sElement) { 
		var	header = "div".setProp("class", "vxJS_queryPopupHeader dragBar").create(),
			closer = "img".setProp([["class", "vxJS_queryPopupCloser"], ["src", "js/assets/window_close.png"], ["title", "Close"]]).create(),
			searchSubmit = "input".setProp([
				["type", "button"],
				["value", "Ok!"],
				["class", "vxJS_queryPopupSearchSubmit"]]).create();
		searchInput	= "input".setProp([
			["value", ""],
			["class", "vxJS_queryPopupSearchInput"]]).create();

		vxJS.event.addListener(closer, "click", hide);
		vxJS.event.addListener(searchSubmit, "click", function() { submit(searchInput.value.trim()); });
		vxJS.event.addListener(searchInput, "keydown",
			function(e) {
				switch(e.keyCode) {
					case 27:
						hide();
						break;
					case 13:
						vxJS.event.preventDefault(e);
						submit(searchInput.value.trim());
						break;
				}
			}
		);
		header.appendChild("div".create([closer, searchInput, searchSubmit]));
		layer.appendChild(header);
	}

	vxJS.event.addListener(list, "select", function() {
		vxJS.event.serve(that, "select", this.getSelected()[0]);
		hide();
	});

	vxJS.event.addListener(list, "cancel", function() {
		hide();
	});

	vxJS.dom.appendChildren(layer, [msgBox, list.element]);
	vxJS.dom.appendChildren(document.body, [layer, xhrImg]);

	vxJS.event.addListener(button, "click", buttonListener);

	vxJS.event.addListener(document, "click", function(){
		if (!vxJS.dom.getParentElement(this, "div.vxJS_queryPopup") && !hidden) {
			hide();
		}
	});

	/**
	 * expose container element
	 */
	that.element = layer;

	/**
	 * expose hooks to attach fx
	 */
	that.show = function() { layer.style.display = ""; };
	that.hide = function() { layer.style.display = "none"; };
	
	/**
	 * set search input value
	 */
	that.setSearchInput = function(v) {
		searchInput.value = v;
	};

	return that;
};