/**
 * Client side code
 *
 * Copyright (c) 2007 - 2008 TOLRA Micro Systems Limited. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * @package fusionLib
 */

/**
 * Core library functions
 */
var fusionLib = new function() {
	var self = this;

	// Find the URL to the library folder
	this.libPath = '';
	var script = document.getElementsByTagName('script').item(0);
	while(script && !this.libPath.length) {
		if(script.src && script.src.indexOf('js/fusionLib.js') != -1)
			this.libPath = script.src.replace(/fusionLib.js$/, '');
		script = script.nextSibling;
	}

	// Load the CSS for the overlay
	document.write('<link type="text/css" href="' + this.libPath + 'overlay.css" rel="stylesheet" media="all" />');

	/**
	 * Events
	 */
	var handlers = [];

	this._findHandler = function(target, eventName, fnHandler) {
		for(i in handlers) {
			if(handlers[i].target == target && handlers[i].eventName == eventName && handlers[i].fnHandler == fnHandler)
				return i;
		}

		return -1;
	};

	// Attach to an event
	this.observe = function(target, eventName, fnHandler) {
		// if given a string look up the object
		if(typeof target == "string") target = document.getElementById(target);

		// Look for an existing handler
		if(self._findHandler(target, eventName, fnHandler) != -1) return;

		// create wrapper event function to fix browser differences
		var fn = function(evt) {
			evt = evt ? evt : (window.event ? window.event : null);
			if(evt) {
				// For IE convert srcElement to target
				if(!evt.target) evt.target = evt.srcElement;

				// if handler returns false don't run default
				if(!fnHandler(evt)) {
					if(evt.stopPropagation) {
						evt.stopPropagation();
						evt.preventDefault();
					}
					else if(evt.cancelBubble) {
						evt.cancelBubble = true;
						evt.returnValue = false;
					}
					return false;
				}
			}
		};

		// Remember handler
		handlers.push({target: target, eventName: eventName, fnHandler: fnHandler, fn: fn});

		// Attach event to object
		if(target.addEventListener)
			target.addEventListener(eventName, fn, false);
		else {
			target.attachEvent("on" + eventName, fn);

			// For IE add unloader to remove all handlers
			if(!window._fusionLibEventUnload) {
				window._fusionLibEventUnload = true;
				self._removeAllEvents = function() {
					for(i in handlers) {
						handlers[i].target.detachEvent("on" + handlers[i].eventName, handlers[i].fn);
					}
				}

				var _oldOnUnload = window.onunload;
				if(typeof window.onunload != 'function') window.onunload = self._removeAllEvents;
				else window.onunload = function() { self._removeAllEvents(); _oldOnUnload(); };
			}
		}
	};

	// Detach event
	this.stopObserving = function(target, eventName, fnHandler) {
		// if given a string look up the object
		if(typeof target == "string") target = document.getElementById(target);

		var idx = self._findHandler(target, eventName, fnHandler);
		if(idx == -1) return;

		// Dettach event from object
		if(target.removeEventListener)
			target.removeEventListener(eventName, handlers[idx].fn, false);
		else
			target.detachEvent("on" + eventName, handlers[idx].fn);

		delete handlers[idx];
	};

	/**
	 * Overlay
	 */
	var xPosOverlay, yPosOverlay;
	var _overlayInit = false;
	var overlayObj;				// Overlay div
	var overlayCtntObj;			// Overlay content div
	var overlayBdyObj;			// Overlay body div
	var overlayCaptionObj;		// Overlay caption div
	var overlayCaption = false;	// Overlay click to close or caption

	// Setup the page to support the overlay
	this._initOverlay = function() {
		if(_overlayInit) return;
		_overlayInit = true;

		// Add divs to body for overlay
		overlayObj = document.createElement("div");
		overlayObj.id = 'fusionLibOverlay';
		overlayObj.style.filter = 'alpha(opacity=80)';
		document.getElementsByTagName('body')[0].appendChild(overlayObj);

		overlayCtntObj = document.createElement("div");
		overlayCtntObj.id = 'fusionLibOvBox';
		document.getElementsByTagName('body')[0].appendChild(overlayCtntObj);

		overlayBdyObj = document.createElement("div");
		overlayBdyObj.id = 'fusionLibOvBdy';
		overlayCtntObj.appendChild(overlayBdyObj);

		overlayCaptionObj = document.createElement("div");
		overlayCaptionObj.id = 'fusionLibOvCap';
		overlayCtntObj.appendChild(overlayCaptionObj);
	};

	/**
	 * Common overlay enable/disable code
	 * Fix IE6 body and HTML, requires height: 100% and overflow: hidden
	 * Also requires scroll position reset
	 */
	this._doOverlay = function(active){

		// Before IE7
		if(!window.XMLHttpRequest) {
			height = active ? '100%' : 'auto';
			overflow = active ? 'hidden' : 'auto';

			// Scroll to top of page
			if(active) {
				xPosOverlay = document.documentElement.scrollLeft;
				yPosOverlay = document.documentElement.scrollTop;
				window.scrollTo(0, 0);
			}

			bodyObj = document.getElementsByTagName('body')[0];
			bodyObj.style.height = height;
			bodyObj.style.overflow = overflow;

			htmlObj = document.getElementsByTagName('html')[0];
			htmlObj.style.height = height;
			htmlObj.style.overflow = overflow;

			// Restore scroll position
			if(!active)
				window.scrollTo(xPosOverlay, yPosOverlay);
		}

		// Hide selects to stop them showing through
		var visibility = active ? 'hidden' : 'visible';
		selects = document.getElementsByTagName('select');
		for(i = 0; i < selects.length; i++) {
			selects[i].style.visibility = visibility;
		}
	};

	// Activate the overlay
	this.overlayActivate = function(click, w, h, caption) {
		overlayCaption = click;
		self._initOverlay();
		self._doOverlay(true);

		// Remove any content
		if(overlayBdyObj.firstChild)
			overlayBdyObj.removeChild(overlayBdyObj.firstChild);
		if(overlayCaptionObj.firstChild)
			overlayCaptionObj.removeChild(overlayCaptionObj.firstChild);

		// Set busy animation
		overlayCtntObj.style.backgroundImage = 'url(' + self.libPath + 'loading.gif)';

		overlayCaptionObj.style.display = 'none';
		overlayCaptionObj.style.backgroundImage = 'none';

		if(click) {
			self.observe(overlayObj, "click", self.overlayDeactivate);
			self.observe(overlayCaptionObj, "click", self.overlayDeactivate);
			overlayCaptionObj.style.display = 'block';
			overlayCaptionObj.style.backgroundImage = 'url(' + self.libPath + 'close.gif)';
		}

		if(caption) {
			overlayCaption = true;
			overlayCaptionObj.style.display = 'block';
			overlayCaptionObj.innerHTML = caption;
		}

		// Size and make visible
		this.overlaySize(w || 250, h || 150);
		overlayObj.style.display = 'block';
		overlayCtntObj.style.display = 'block';
	};

	// Activate the overlay
	this.overlayDeactivate = function() {
		self._initOverlay();
		self._doOverlay(false);
		overlayObj.style.display = 'none';
		overlayCtntObj.style.display = 'none';

		// Remove event handlers
		self.stopObserving(overlayObj, "click", self.overlayDeactivate);
		self.stopObserving(overlayCtntObj, "click", self.overlayDeactivate);
	};

	// Set the size of the overlay content window
	this.overlaySize = function(w, h) {
		overlayBdyObj.style.height = h.toString() + 'px';
		if(overlayCaption) h += 46;
		overlayCtntObj.style.width = w.toString() + 'px';
		overlayCtntObj.style.marginLeft = (-Math.floor(w * .5)).toString() + 'px';
		overlayCtntObj.style.height = h.toString() + 'px';
		overlayCtntObj.style.marginTop = (-Math.floor(h * .5)).toString() + 'px';
	};

	// Write content to overlay window
	this.overlayContent = function(content) {
		overlayBdyObj.innerHTML = content;
	};

	// Get the content window object
	this.overlayObject = function() {
		return overlayBdyObj;
	};
};
