///////////////////////////////////////////////////
// The Qcodo Object is used for everything in Qcodo
///////////////////////////////////////////////////

	var qcodo = {
		initialize: function() {

		////////////////////////////////
		// Browser-related functionality
		////////////////////////////////

			this.browser = (function() {
				var ua = navigator.userAgent.toLowerCase();
				var browser = { webkit: false, opera: false, ie: false, mozilla: false };

				var match = /(webkit)[ \/]([\w.]+)/.exec( ua ) ||
					/(opera)(?:.*version)?[ \/]([\w.]+)/.exec( ua ) ||
					/(msie) ([\w.]+)/.exec( ua ) ||
					!/compatible/.test( ua ) && /(mozilla)(?:.*? rv:([\w.]+))?/.exec( ua ) ||
					[];
				if (match[1]=='msie') match[1] = 'ie';
				if (match[1]) browser[match[1]] = true;

				browser.version = match[2] || "0";

				browser.platform = {
					mac: /mac/.test(ua),
					win: /win/.test(ua),
					linux: /linux/.test(ua),
					android: /android \d\.\d/.test(ua),
					iphoneos: /apple.*mobile.*safari/.test(ua)
				};

				return browser;
			})();

			this.loadJavaScriptFile = function(strScript, objCallback) {
				if(strScript.substring(0,7) != 'http://' && strScript.substring(0,8) != 'https://') strScript = qc.jsAssets + "/" + strScript;
				var objNewScriptInclude = document.createElement("script");
				objNewScriptInclude.setAttribute("type", "text/javascript");
				objNewScriptInclude.setAttribute("src", strScript);
				this.objForm.appendChild(objNewScriptInclude);

				// IE does things differently
				if (qcodo.browser.ie) {
					objNewScriptInclude.callOnLoad = objCallback;
					objNewScriptInclude.onreadystatechange = function() {
						if ((this.readyState == "complete") || (this.readyState == "loaded"))
							if (this.callOnLoad)
								this.callOnLoad();
					}
				} else
					objNewScriptInclude.onload = objCallback;
			};

			this.loadStyleSheetFile = function(strStyleSheetFile, strMediaType) {
				strStyleSheetFile = qc.cssAssets + "/" + strStyleSheetFile;

				var objLink = document.createElement('link')
				objLink.rel = 'stylesheet';
				objLink.type = 'text/css';
				objLink.href = strStyleSheetFile;
				objLink.media = strMediaType;

				if ( typeof objLink != undefined ) {
					document.getElementsByTagName("head")[0].appendChild(objLink);
				}
			};

			this.computedStyle = function(elem) {
				return elem.currentStyle ? elem.currentStyle : window.getComputedStyle(elem, null);
			}

			this.setOpacity = function(elem, intOpacity) {
				var reOpacity = /alpha\s*\(\s*opacity\s*=\s*([^\)]+)\)/;

				if (typeof elem.style.opacity == 'string')
					elem.style.opacity = intOpacity;
				else {
					var es = elem.style;
					es.zoom = 1;
					if (reOpacity.test(es.filter)) {
						intOpacity = intOpacity >= 0.9999 ? '' : ('alpha(opacity=' + (intOpacity * 100) + ')');
						es.filter = es.filter.replace(reOpacity, intOpacity);
					}
					else
						es.filter += ' alpha(opacity=' + (intOpacity * 100) + ')';
				}
			};

			this.boxModel = function() {
				var boxModel;
				var div = document.createElement("div");
				div.style.width = div.style.paddingLeft = "1px";

				document.body.appendChild( div );
 				boxModel = div.offsetWidth === 2;
				document.body.removeChild( div ).style.display = 'none';

				div = null;
				return boxModel;
			};

			// CSS1Compat - standards mode (false), BackCompat - quirks mode (true)
			this.compatMode = (function() { return window.document.compatMode === "BackCompat"; })();


		/////////////////////////////
		// QForm-related functionality
		/////////////////////////////

			this.objForm = null;
			this.strFormId = null;

			this.registerForm = function(strFormId, strFormState) {
				this.strFormId = strFormId;
				this.objForm = document.getElementById(strFormId);

				// Register the Various Hidden Form Elements needed for QForms
				this.registerFormHiddenElement("Qform__FormId", document);
				this.registerFormHiddenElement("Qform__FormState", document);
				this.registerFormHiddenElement("Qform__FormControl", document);
				this.registerFormHiddenElement("Qform__FormEvent", document);
				this.registerFormHiddenElement("Qform__FormParameter", document);
				this.registerFormHiddenElement("Qform__FormCallType", document);
				this.registerFormHiddenElement("Qform__FormUpdates", document);
				this.registerFormHiddenElement("Qform__FormCheckableControls", document);
				
				// Set the QForm's FormId and FormState
				document.getElementById("Qform__FormId").value = strFormId;
				document.getElementById("Qform__FormState").value = strFormState;

				//qcodo.loadFirebugLite();
			};

			this.registerFormHiddenElement = function(strId, objDocument) {
				var objHiddenElement = objDocument.createElement("input");
				objHiddenElement.type = "hidden";
				objHiddenElement.id = strId;
				objHiddenElement.name = strId;
				this.objForm.appendChild(objHiddenElement);
			};

			this.wrappers = new Array();

			this.registerAssetLocations = function(strJsAssets, strPhpAssets, strCssAssets, strImageAssets) {
				qc.jsAssets = strJsAssets;
				qc.phpAssets = strPhpAssets;
				qc.cssAssets = strCssAssets;
				qc.imageAssets = strImageAssets;
			};

		////////////////////////////////////
		// URL Hash Processing
		////////////////////////////////////

			this.processHashCurrent = null;
			this.processHashIntervalId = null;
			this.processHashControlId = null;

			this.registerHashProcessor = function(strControlId, intPollingInterval) {
				this.processHashCurrent = null;
				this.processHashControlId = strControlId;

				//use native event
				if ( 'onhashchange' in window )
					window.onhashchange = this.processHash;
				else
					this.processHashIntervalId = setInterval("qc.processHash();", intPollingInterval);

				//fire processor once to process hash on load instantly not waiting for interval
				this.processHash();
			};

			this.processHash = function() {
				// Get the Hash Value
				var strUrl = new String(document.location);

				// Only Proceed if it's different than before
				if (qc.processHashCurrent != strUrl.toString()) {
					// Update the stored current hash stuff
					qc.processHashCurrent = strUrl.toString();

					// Figure out the Hash data
					var strHashData = qc.getHashContent();

					// Make the callback
					qc.pA(qc.strFormId, qc.processHashControlId, 'QClickEvent', strHashData, null);
				};
			};

			this.getHashContent = function() {
				var intPosition = qc.processHashCurrent.indexOf('#');
				var strHashData = "";

				if (intPosition > 0) strHashData = qc.processHashCurrent.substring(intPosition + 1);
				return strHashData;
			};

			this.clearHashProcessor = function() {
				//clear native event
				if ( 'onhashchange' in window )
					window.onhashchange = null;

				if (this.processHashIntervalId)
					clearInterval(this.processHashIntervalId);
			};

		////////////////////////////////////
		// Polling Processing
		////////////////////////////////////
			
			this.registerPollingProcessor = function(strControlId, intPollingInterval) {
				setTimeout("qc.processPolling('" + strControlId + "');", intPollingInterval);
			};

			this.processPolling = function(strControlId) {
				// Make the callback
				qc.pA(qc.strFormId, strControlId, 'QClickEvent');
			};

		////////////////////////////////////
		// Mouse Drag Handling Functionality
		////////////////////////////////////

			this.enableMouseDrag = function() {
				document.onmousedown = this.handleMouseDown;
				document.onmousemove = this.handleMouseMove;
				document.onmouseup = this.handleMouseUp;
			};

			this.handleMouseDown = function(event) {
				event = qcodo.handleEvent(event);

				var objHandle = event.target;
				if (!objHandle) return true;

				var objWrapper = objHandle.wrapper;
				if (!objWrapper) return true;

				// Qcodo-Wide Mouse Handling Functions only operate on the Left Mouse Button
				// (Control-specific events can respond to QRightMouse-based Events)
				if (qcodo.mouse.left) {
					if (objWrapper.handleMouseDown) {
						// Specifically for Microsoft IE
						if (objHandle.setCapture)
							objHandle.setCapture();

						// Ensure the Cleanliness of Dragging
						objHandle.onmouseout = null;
						if (document.selection)
							document.selection.empty();

						qcodo.currentMouseHandleControl = objWrapper;
						return objWrapper.handleMouseDown(event, objHandle);
					}
				}

				this.currentMouseHandleControl = null;
				return true;
			};

			this.handleMouseMove = function(event) {
				event = qcodo.handleEvent(event);

				if (qcodo.currentMouseHandleControl) {
					var objWrapper = qcodo.currentMouseHandleControl;
					var objHandle = objWrapper.handle;

					// In case IE accidentally marks a selection...
					if (document.selection)
						document.selection.empty();

					if (objWrapper.handleMouseMove)
						return objWrapper.handleMouseMove(this, objHandle);
				}

				return true;
			};

			this.handleMouseUp = function(event) {
				event = qcodo.handleEvent(event);

				if (qcodo.currentMouseHandleControl) {
					var objWrapper = qcodo.currentMouseHandleControl;
					var objHandle = objWrapper.handle;

					// In case IE accidentally marks a selection...
					if (document.selection)
						document.selection.empty();

					// For IE to release release/setCapture
					if (objHandle.releaseCapture) {
						objHandle.releaseCapture();
						objHandle.onmouseout = function() { this.releaseCapture() };
					};

					qcodo.currentMouseHandleControl = null;

					if (objWrapper.handleMouseUp)
						return objWrapper.handleMouseUp(event, objHandle);
				}

				return true;
			};

		////////////////////////////////////
		// Window Unloading
		////////////////////////////////////

			this.unloadFlag = false;
			this.handleUnload = function() {
				this.unloadFlag = true;
			};
			window.onunload= this.handleUnload;

			this.beforeUnloadFlag = false;
			this.handleBeforeUnload = function() {
				this.beforeUnloadFlag = true;
			};
			window.onbeforeunload= this.handleBeforeUnload;
		}
	};

////////////////////////////////
// Qcodo Shortcut and Initialize
////////////////////////////////

	var qc = qcodo;
	qc.initialize();
	qc.regAL = qcodo.registerAssetLocations;
	qc.regHP = qcodo.registerHashProcessor;
	qc.clrHP = qcodo.clearHashProcessor;
	qc.regPP = qcodo.registerPollingProcessor;
