// needed by QWebControl.zIndexFixIE
var iaz_preserved_elements = [];
var iaz_preserved_zindexes = [];

var QWebControl = QObject.extend ('QWebControl',
{
	/**
	 * The list of delegates set by the server
	 */
	delegates : {},
	/**
	 * The list of chid controls
	 */
	controls : new Array(),
	/**
	 * The parent control
	 */
	parent : null,
	/**
	 * Link to the DOM Element for this web Control
	 */
	domElement : null,
	/**
	 * This parameters can be used by PHP to send data to this JS object
	 * their use it's optional
	 */
	_js_shared_params : null,
	
	_js_updated_params : {},
	/**
	 * The full id of the control
	 */
	fullId : null,
	/**
	 * The relative (to it's parent) id of the object
	 */
	id : null,
	/**
	 * The web path to the resource location (relative to base_href)
	 */
	resPath : null,

	/**
	 * This is the constructor
	 */
	init : function() // can add params
	{
		
	},

	/**
	 * This function is for internal usage , do not overrite or change
	 */
	initControls : function()
	{
		this.root = GetQWebPage();
		
		this.objectName = this.fullId + "_obj";
		window[this.objectName] = this;

		if (this.doInitControls)
		{
			this.doInitControls();
			delete(this.doInitControls);
		}

		if (this.controls)
		{
			// for (var c in this.controls)
			for (var i = 0; i < this.controls.length; i++)
				this.controls[i].initControls();
		}

		this.attachEvents();
	},

	load : function ()
	{
		// alert(this.fullId);
	},

	/**
	 * Get a JS param sent from the server (if any was sent)
	 * The usage of JS params is optional
	 */
	getJsParam : function (key)
	{
		if (this._js_shared_params && this._js_shared_params[key])
			return this._js_shared_params[key];
		else
			return null;
	},
	
	hasJsParamUpdated : function (key)
	{
		if (this._js_updated_params[key])
			return this._js_updated_params[key];
		else
			return false;
	},
	
	hasJsParamUpdatedAndSet : function (key)
	{
		return (this._js_shared_params && this.hasJsParamUpdated(key) && this._js_shared_params[key]);
	},

	/**
	 * You can also set one of the JS params
	 * It will NOT be sent to the server at the moment
	 */
	setJsParam : function (key, value)
	{
		if (!this._js_shared_params)
			this._js_shared_params = {};
		this._js_shared_params[key] = value;
	},

	/**
	 * Unsets a JS param
	 */
	unsetJsParam : function (key)
	{
		if (!this._js_shared_params)
			return false;
		if (this._js_shared_params[key])
		{
			delete this._js_shared_params[key];
			return true;
		}
		else
			return false;
	},

	/**
	 * The server will call this function if the JS params of this object were updated
	 * and the control was not reloaded
	 */
	onJsParamsUpdated : function ()
	{

	},

	/**
	 * Internal function , do not change !
	 */
	_setJsSharedParams : function (params, quick_load)
	{
		if ((!params) || (params.length < 1))
			return;

		for (var x in this._js_updated_params)
			this._js_updated_params[x] = false;

		if (!this._js_shared_params)
			this._js_shared_params = {};
		for (var key in params)
		{
			this._js_shared_params[key] = params[key];
			this._js_updated_params[key] = true;
		}
		
		// this._print_js_updated_params();
		
		if (quick_load)
		{
			// alert(params);
			this.onJsParamsUpdated();
			jQuery(this).trigger("ev_jsParamsUpdated");
		}

	},
	
	_print_js_updated_params : function ()
	{
		var str = "Id: " + this.fullId + "\n";
		if (this._js_updated_params)
		{
			for (var x in this._js_updated_params)
				str += x + " = " + this._js_updated_params[x] + "\n";
		}
		alert(str);
	},

	trigger : function (eventType, extraParameters)
	{
		jQuery(this).trigger(eventType, extraParameters);
	},

	bind : function (eventType, eventData, eventObject)
	{
		jQuery(this).bind(eventType, eventData, eventObject);
	},

	unbindAll : function (event)
	{
		jQuery(this).unbind(event);
	},

	unbind : function (event, callback)
	{
		jQuery(this).unbind(event, callback);
	},
	/**
	 * Internal function , do not change !
	 */
	triggerLoadControls : function ()
	{
		this.load();

		if (this.controls)
		{
			for (var i = 0; i < this.controls.length; i++)
				this.controls[i].triggerLoadControls();
		}

		jQuery(this).trigger("ev_load");
		
		if (this._internalAfterLoad)
			this._internalAfterLoad();
	},

	/**
	 * Ads a server side delegate
	 */
	addDelegate : function (event_type, delegate_as_json)
	{
		event_type = this.decodeEventType(event_type);

		if (!this.delegates[event_type])
			this.delegates[event_type] = new Array();
		this.delegates[event_type][this.delegates[event_type].length] = delegate_as_json;
	},

	/**
	 * Internal function , do not change !
	 */
	decodeEventType : function (event_type)
	{
		switch (event_type)
		{
			case "1":
			{
				return "onclick";
			}
			default:
			{
				return event_type;
			}
		}
	},

	/**
	 * Internal function , do not change !
	 */
	encodeEventType : function (event_type)
	{
		if (event_type == "onclick")
		{
			return 1;
		}
		else
		{
			// alert("Error: Unknown event type");
			return event_type;
		}
	},

	/**
	 * Removes a server side delegate
	 */
	removeDelegate : function (event_type, delegate_type, callback_object_id, callback_method)
	{
		alert("WebControl::removeDelegate not implemented yet");
		/*
		if (this.delegates[event_type][callback_object_id][callback_method])
			delete this.delegates[event_type][callback_object_id][callback_method];
		*/
	},

	/**
	 * Internal function , do not change !
	 */
	processEvent : function(event, event_type)
	{
		// you may extract patams from event and put them in the callback params
		for (var i = 0; i < this.delegates[event_type].length; i++)
		{
			// var delegate = this.delegates[event_type][x];
			var delegate = this.delegates[event_type][i];

			if (delegate.type == "QWebAjaxDelegate")
			{
				this.ajaxCallback(event_type);
			}
			else if (delegate.type == "QWebJsDelegate")
			{
				// alert("WebControl::processEvent(QWebJsDelegate) not implemented yet");
			}
			else if (delegate.type == "QWebDelegate")
			{
				// alert("WebControl::processEvent(QWebDelegate) not implemented yet");
			}
		}
	},
	
	onAfterEvent : function (event_type, postback_data)
	{
		
	},

	triggerEvent : function (event_type, postback_data, callback_object, callback_method)
	{
		this.ajaxCallback(event_type, postback_data, callback_object, callback_method);
	},
	
	triggerEvents : function (events, callback_object, callback_method)
	{
		// alert("triggerEvent");
		// this.ajaxCallback(event_type, postback_data, callback_object, callback_method);
		this.ajaxCallbackEvents(events, callback_object, callback_method);
	},
	
	ajaxCallbackEvents : function (events, callback_object, callback_method)
	{
		// build callback stack
		var send_vars = "";
		var send_pos = 0;
		
		for (var i = 0; i < this.root.call_stack.length; i++)
		{
			if (send_pos > 0)
				send_vars += "&";
			send_vars += "__qwl" + send_pos + "=" + urlencode(this.root.call_stack[i]);

			send_pos++;
		}
		
		var ref_this = this;

		send_vars += "&__qajax=1";
		send_vars += "&__qid=" + urlencode(this.root.instance_id);

		this.showLoadingIcon();
		// var events = events;// [{id: this.fullId, type: this.encodeEventType(event_type), params: postback_data}];

		jQuery.ajax({
			type: "POST",
			url: this.root.base_href + this.root.request_url + "?" + send_vars,
			data: {"__wb_events" : JSON.stringify(events)},
			dataType : "text",
			success: function (msg) {
				try
				{
					eval(msg);
				
					if (callback_object && callback_method)
						eval("callback_object." + callback_method + "(msg);");
						
					ref_this.hideLoadingIcon();
				}
				catch (ex)
				{
					var err_msg;
					if (ex.message)
						err_msg = ex.message;
					else
						err_msg = ex;

					GetQWebPage().setDebugText(err_msg + "<br/>\n<br/>\n<br/>\n================================================================================<br/>\n<br/>\n<br/>\n" + msg, true);
					
					ref_this.hideLoadingIcon();
				}
			},
			error: function (request, textStatus, errorThrown)
			{
				ref_this.hideLoadingIcon();
				alert(textStatus + " : " + request.status);
            }
		});
	},
	
	ajaxCallback : function (event_type, postback_data, callback_object, callback_method)
	{
		this.ajaxCallbackEvents([{id: this.fullId, type: this.encodeEventType(event_type), params: postback_data}], callback_object, callback_method);
	},
	
	showLoadingIcon : function()
	{
		GetQWebPage().showLoadingIcon();
	},
	
	hideLoadingIcon : function()
	{
		GetQWebPage().hideLoadingIcon();
	},

	/**
	 * Gets the data in a form
	 */
	getFormParameters : function (form_name)
	{
		var form_el = null;
		// alert(typeof(form_name));
		
		if (form_name)
		{
			if (typeof(form_name) != "string")
				form_el = form_name;
			else
				form_el = document.forms[form_name];
		}
		else
		{
			form_el = this.domElement.getElementsByTagName("form");
			if (form_el && (form_el.length > 0))
				form_el = form_el[0];
			else
				return null;
		}
		
		// return jQuery(form_el).serializeArray();

		var inps = form_el.getElementsByTagName("input");
		var sels = form_el.getElementsByTagName("select");
		var texts = form_el.getElementsByTagName("textarea");

		var all = {};

		for (var x=0; x<inps.length; x++)
		{
			var inp_type = inps[x].getAttribute("type");
			if (((inp_type == "checkbox") || (inp_type == "radio")) && (!inps[x].checked))
				continue;

			// all[inps[x].name] = inps[x].value;
			this.getFormParametersSetInputData(all, inps[x].name, jQuery(inps[x]).val());
		}
		for (var x=0; x<sels.length; x++) this.getFormParametersSetInputData(all, sels[x].name, jQuery(sels[x]).val());
		for (var x=0; x<texts.length; x++) this.getFormParametersSetInputData(all, texts[x].name, jQuery(texts[x]).val());

		// alert( this.dump(all, 5, true) );

		return all;
	},
	
	getFormParametersSetInputData : function(object, input_name, value)
	{
		var br_pos = 0;
		var paths = [];
		while (br_pos >= 0)
		{
			var new_br_pos = input_name.indexOf("[", br_pos);
			if ((br_pos == 0) && (new_br_pos > 0))
			{
				paths.push(input_name.substr(0, new_br_pos));
			}
			br_pos = new_br_pos;
			if (br_pos >= 0)
			{
				var end = input_name.indexOf("]", br_pos + 1);
				if (end >= 0)
				{
					var key = input_name.substr(br_pos + 1, end - br_pos - 1);
					paths.push(key);
					br_pos = end + 1;
				}
				else
					break;
			}
			else
				break;
		}
		
		if (paths.length > 0)
		{
			var obj = object;
			var str = "";
			for (var i = 0; i < paths.length; i++)
			{
				str += "[" + paths[i] + "]";
				
				if (i == (paths.length - 1))
				{
					obj[paths[i]] = value;
					return;
				}
				else
				{
					if (obj[paths[i]] === undefined)
						obj[paths[i]] = {};
					obj = obj[paths[i]];
				}
			}
		}
		else
		{
			object[input_name] = value;
		}
	},

	attachEvents : function()
	{
		// alert("attaching events");
		if (this.delegates)
		{
			for (var event_type in this.delegates)
			// for (var i = 0; i < this.this.root.call_stack.length; i++)
			{
				if (typeof(this.delegates[event_type]) == "function")
					continue;
				// alert("attachEvents");
				if (!this.domElement)
					throw "DOM Element for [" + this.fullId + "] can not be null";
				CrossBrowserAddEventHandler(this.domElement, event_type,
					new Function("e", "window[\"" + this.objectName + "\"].processEvent(e, \"" + event_type + "\")"));
			}
		}
	},

	removeControl : function(child)
	{
		if (this.controls.indexOf(child) >= 0)
		{
			child.doDestroyControl();

			this.controls.splice(this.controls.indexOf(child), 1);
			if (GetQWebPage().controls_index[child.fullId])
				delete(GetQWebPage().controls_index[child.fullId]);

			return true;
		}
		else
			return false;
	},

	doDestroyControl : function()
	{
		for (var i = 0; i < this.controls.length; i++)
			this.controls[i].doDestroyControl();

		this.destroyControl();
		this.trigger("ev_destroy");
	},

	destroyControl : function()
	{

	},

	addControl : function(control)
	{
		if (control.isWebPage())
			throw "Can not add a web page as a control";
		
		this.controls[this.controls.length] = control;
		control.parent = this;
		control.root = GetQWebPage();

		control.root.controls_index[control.fullId] = control;
	},

	removeSelf : function()
	{
		if (this.parent)
			this.parent.removeControl(this);
	},

	setBounds : function(top, left, width, height, trigger_event)
	{
		// alert(top + " x " + left + " x " + width + " x " + height);

		var jq_ctrl = jQuery(this.domElement);
		jq_ctrl.css("top", top).css("left", left).css("width", width).css("height", height);

		if (trigger_event)
		{
			// alert("trigger_event for: " + this.fullId);
			jQuery(this.domElement).trigger( "ev_boundsChanged", this );
		}
	},
	
	getChildById : function (id)
	{
		if (this.controls)
		{
			for (var i = 0; i < this.controls.length; i++)
				if (this.controls[i].id == id)
					return this.controls[i];
		}
		return null;
	},

	dumpObject : function (obj, max_depth, show_value)
	{
		if (!max_depth)
			max_depth = 3;

		var dump_str = {};
		dump_str.value = "";
		this.dumpObjectRecurse(obj, max_depth, 0, dump_str, show_value);
		return dump_str.value;
	},
	
	dump : function (obj, max_depth, show_value)
	{
		return this.dumpObject(obj, max_depth, show_value);
	},

	dumpObjectRecurse : function (obj, max_depth, depth, dump_str, show_value)
	{
		if (depth >= max_depth)
			return;

		var spaces = "";
		for (var i = 0; i < (depth * 4); i++)
			spaces += " ";

		for (var y in obj)
		{
			if (show_value)
				dump_str.value += spaces + y + " = " + typeof(obj[y]) + " = " + obj[y] + "\n";
			else
				dump_str.value += spaces + y + " = " + typeof(obj[y]) + "\n";
			if (typeof(obj[y]) == "object")
				this.dumpObjectRecurse(obj[y], max_depth, depth + 1, dump_str, show_value);
		}

		// alert(dump_str);
	},

	getWebPage : function()
	{
		return GetQWebPage();
	},

	hide : function()
	{
		jQuery(this.domElement).hide();
	},
	
	res : function (url)
	{
		return this.resPath + url;
	},
	
	getLang : function (key)
	{
		if (!key)
		{
			if (window["QLanguages"] && window["QLanguages"]["language"])
				return window.QLanguages.language;
			else
				return null;
		}
		else
		{
			if (window["QLanguages"] && window["QLanguages"]["Get"])
				return QLanguages.Get(key);
			else
				return null;
		}
	},
	
	isWebPage : function ()
	{
		return false;
	},
	
	jQuery : function (find)
	{
		if (this.domElement)
		{
			if (find)
				return jQuery(find, this.domElement);
			else
				return jQuery(this.domElement);
		}
		else
			return null;
	},
	
	replaceSeoLinksWithAjax : function ()
	{
		var wp = GetQWebPage();
		this.jQuery("a.___ax").each(function()
			{
				var jq = jQuery(this);
				if (jq.length > 0)
				{
					var href = jq.attr("href");
					if (href)
					{
						if (href.substr(0, wp.base_href.length) == wp.base_href)
							href = href.substr(wp.base_href.length);
						else if (href.substr(0, wp.base_href.length - 1) == wp.base_href.substr(0, wp.base_href.length - 1))
							href = href.substr(wp.base_href.length - 1);
						if ((href.length > 0) && (href.substr(0, 1) == "#"))
						{
							// nothing, already tagged
						}
						else
						{
							// just for now 
							if (wp && wp["languagePrefix"] && 
								(href.substr(0, 2) == wp["languagePrefix"]) && 
								((href.substr(2, 1) == "/")||(href.length == 2)))
							{
								if (href.length > 2)
									jq.attr("href", wp["languagePrefix"] + "#" + href.substr(3));
								else
									jq.attr("href", wp["languagePrefix"]);
									
								// alert( jq.attr("href") );
							}
							else
								jq.attr("href", "#" + href);
						}
					}
				}
			});
	},
	
	setHash : function (hash)
	{
		GetQWebPage().setHash(hash);
	},
	
	getBaseHref : function ()
	{
		return GetQWebPage().base_href;
	}

	/*
	zIndexFixIE : function (element, zindex, context_id)
	{
		// only for IE
		if (!jQuery.browser.msie)
			return;
		// default values
		if (undefined == zindex)
			zindex = 1;

		var context = (undefined == context_id ? jQuery("#" + context_id) : jQuery(document.body));
		var element = jQuery(element);

		// undo past zIndexFixIE()
		for (var i = iaz_preserved_elements.length-1; i >= 0; i--)
			iaz_preserved_elements[i].css('z-index', iaz_preserved_zindexes[i]);

		iaz_preserved_elements = [];
		iaz_preserved_zindexes = [];

		// find relative-positioned parents of element within context
		element.parents().each(
			function()
			{
				// alert(this.tagName);
				if ('relative' == jQuery(this).css('position'))
				{
					// preserve ancestor's current z-index
					// alert(this.tagName);
					iaz_preserved_elements.push(jQuery(this));
					iaz_preserved_zindexes.push(jQuery(this).css('z-index') );

					// apply z-index to ancestor
					jQuery(this).css('z-index', zindex);
					// return false;
				}

				// if context found, stop looping
				if (this == context[0])
				{
					alert("breaking out : " + context[0].tagName);
					return false;
				}
			}
		);
	}
	*/
});

