/* gui.js
 * Requirements:
 *     the prototype library must be loaded before this script is loaded
 */

if (typeof Prototype.Browser.Version === 'undefined') {
	if (Prototype.Browser.IE) {
		var ua = new String(navigator.userAgent);
		var offset = ua.indexOf("MSIE ");
		Prototype.Browser.Version = parseFloat(ua.substring(offset + 5, ua.indexOf(";", offset)));
	}
}

if (!("console" in window) || !("log" in console)) {
	if (!("console" in window)) {
		window.console = {};
	}
	if (!("log" in console)) {
		window.console["log"] = function(){};
	}
}

var ModalBoxShading = Class.create({
	_setSize: function() {
		var dim = document.viewport.getDimensions();
		if (Prototype.Browser.WebKit) {
			dim.width = document.body.scrollWidth;
			dim.height = document.body.scrollHeight;
		}
		else if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			dim.width = Math.max(document.documentElement.clientWidth, document.body.clientWidth);
			dim.height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
		}
		else {
			dim.width = Math.max(dim.width, document.documentElement.offsetWidth);
			dim.height = Math.max(dim.height, document.documentElement.offsetHeight);
		}
		if (this._element.offsetHeight != dim.height) {
			this._element.style.height = dim.height + 'px';
		}
		if (this._element.offsetWidth != dim.width) {
			this._element.style.width = dim.width + 'px';
		}
	},
	_eventOnResize: function(e) {
		this._setSize();
		return;
	},
	_eventOnLoad: function(e) {
		document.body.appendChild(this._element);
		this._loaded = true;
		if (this._showOnLoad === true) {
			this._showOnLoad = false;
			this.show();
		}
	},
	setZIndex: function(zIndex) {
		if (typeof zIndex !== 'undefined') {
			this._element.style.zIndex = zIndex;
		}
		else {
			this._element.style.zIndex = 100000;
		}
	},
	initialize: function(zIndex) {
		this._loaded = false;
		this._showOnLoad = false;
		
		this._element = new Element('div');
		this._element.style.backgroundColor = '#000';
		this._element.setOpacity(0.3);
		this.setZIndex(zIndex);
		if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			this._element.style.position = 'absolute';
		}
		else {
			this._element.style.position = 'fixed';
		}
		this._element.style.display = 'none';
		this._element.style.margin = '0px';
		this._element.style.padding = '0px';
		this._element.style.top = '0px';
		this._element.style.left = '0px';
		this._element.style.bottom = '0px';
		this._element.style.right = '0px';
		
		Event.observe(window, 'resize', this._eventOnResize.bindAsEventListener(this));
		if (document.loaded) {
			this._eventOnLoad.bind(this).defer();
		}
		else {
			Event.observe(window, 'load', this._eventOnLoad.bindAsEventListener(this));
		}
	},
	show: function() {
		if (this._loaded === false) {
			this._showOnLoad = true;
		}
		else {
			this._setSize();
			this._element.show();
		}
	},
	hide: function() {
		if (this._loaded === false) {
			this._showOnLoad = false;
		}
		else {
			this._element.hide();
		}
	}
});

var ModalBox = Class.create({
	_setPosition: function() {
		var dim = this._element.getDimensions();
		this._element.style.top = (typeof this._top !== 'undefined') ? this._top : Math.max(0, document.body.parentNode.clientHeight / 2 - dim.height / 2) + 'px';
		this._element.style.left = (typeof this._left !== 'undefined') ? this._left: Math.max(0, document.body.parentNode.clientWidth / 2 - dim.width / 2) + 'px';
	},
	_eventOnResize: function(e) {
		this._setPosition();
	},
	_eventOnLoad: function(e) {
		document.body.appendChild(this._element);
		this._element.appendChild(this._content);
		this._loaded = true;
		if (this._showOnLoad === true) {
			this._showOnLoad = false;
			this.show();
		}
	},
	initialize: function(content, top, left) {
		this._loaded = false;
		this._showOnLoad = false;
		
		this._element = new Element('div');
		this._element.style.zIndex = 1000001;
		if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			this._element.style.position = 'absolute';
		}
		else {
			this._element.style.position = 'fixed';
		}
		this._element.style.display = 'none';
		this._element.style.margin = '0px';
		this._element.style.padding = '0px';
		
		this._content = content;
		this._content.show();
		
		this._top = top;
		this._left = left;
		
		this._shading = new ModalBoxShading();

		Event.observe(window, 'resize', this._eventOnResize.bindAsEventListener(this));
		if (document.loaded) {
			this._eventOnLoad.bind(this).defer();
		}
		else {
			Event.observe(window, 'load', this._eventOnLoad.bindAsEventListener(this));
		}
	},
	show: function() {
		if (this._loaded === false) {
			this._showOnLoad = true;
		}
		else {
			this._setPosition();
			this._shading.show();
			this._element.show();
		}
	},
	hide: function() {
		if (this._loaded === false) {
			this._showOnLoad = false;
		}
		else {
			this._element.hide();
			this._shading.hide();
		}
	}
});

var Hint = Class.create({
	initialize: function(element, message, position, autoFade) {
		this.message = message;
		this.attachedElement = $(element);
		if (typeof position != 'undefined') {
			var map = {
				"under": "under",
				"below": "under",
				"bottom": "under",
				"over": "over",
				"above": "over",
				"top": "over",
				"left": "left",
				"right": "right"
			};
			position = map[position.toLowerCase()];
		}
		if (typeof position == 'undefined') {
			position = 'under';
		}
		this.position = position.slice(0, 1).toUpperCase() + position.slice(1);
		this.autoFade = autoFade;

		this.hintElement = new Element('div', { 'class': 'kasHint kasHint' + this.position, 'style': 'display: none;', 'id': 'kasHint_' + this.attachedElement.identify()}).update(this.message);
		this.hintElement.appendChild(new Element('span', { 'class': 'pointer' }));
		this.visible = false;
		
		if (!document.loaded)
			this.addElement.bind(this).defer();
		else
			this.addElement();
	},
	addElement: function() {
		document.body.appendChild(this.hintElement);
	},
	updatePosition: function() {
		var parentVisible = true;
		for (var parent = this.attachedElement.parentNode;
			 parent != null && parent.nodeName != 'HTML';
			 parent = parent.parentNode) {
			if (!Element.visible(parent)) {
				parentVisible = false;
				break;
			}
		}
		if (this.attachedElement.visible() && parentVisible) {
			var position;
			position = this.attachedElement.cumulativeOffset();
			var dimensions = this.attachedElement.getDimensions();
			switch (this.position) {
				case 'Right':
					position[1] += (dimensions.height / 2) - 12;	// top
					position[0] += (dimensions.width + 16);			// left
					break;
				case 'Under':
				default:
					position[1] += (dimensions.height + 16);		// top
					position[0] += (dimensions.width / 2) - 16;		// left
					var hintDim = this.hintElement.getDimensions();
					if (position[0] + hintDim.width >= document.body.getWidth()) {
						position[0] -= (hintDim.width - 29);
						this.hintElement.select('span.pointer')[0].style.left = (hintDim.width - 24) + 'px';
					}
					else {
						this.hintElement.select('span.pointer')[0].style.left = "5px";
					}
					if (position[1] + hintDim.height >= document.body.getHeight()) {
						position[1] -= (dimensions.height + 24 + hintDim.height);
						if (this.hintElement.hasClassName("kasHintUnder"))
							this.hintElement.removeClassName("kasHintUnder");
						this.hintElement.addClassName("kasHintOver");
					}
					else {
						if (this.hintElement.hasClassName("kasHintOver"))
							this.hintElement.removeClassName("kasHintOver");
						this.hintElement.addClassName("kasHintUnder");
					}
					break;
			}
			this.hintElement.style.top = position[1] + 'px';
			this.hintElement.style.left = position[0] + 'px';
			return true;
		}
		return false;
	},
	show: function() {
		if (this.updatePosition()) {
			this.hintElement.show();
			this.visible = true;
			if (typeof this.autoFade != 'undefined' && parseInt(this.autoFade) > 0) {
				this.autoFadeTimeout = setTimeout(this.hide.bind(this), parseInt(this.autoFade));
			}
		}
		else {
			this.show.bind(this).defer();
		}
	},
	hide: function() {
		this.hintElement.hide();
		this.visible = false;
		if (typeof this.autoFadeTimeout != 'undefined') {
			clearTimeout(this.autoFadeTimeout);
		}
	}
});

var HintToolTip = Class.create(Hint, {
	initialize: function($super, element) {
		var content;
		var spans = element.select('span');
		if (spans.length > 0)
			content = spans[0].innerHTML;
		else if (element.title != "") {
			content = element.title;
		}
		else
			content = "ERROR: Unable to load tool tip text";
		element.title = "";
		$super(element, content, 'under');
		Event.observe(element, 'mouseover', this.mouseOver.bindAsEventListener(this));
		Event.observe(element, 'mouseout', this.mouseOut.bindAsEventListener(this));
	},
	mouseOver: function(e) {
		e.stop();
		this.show();
	},
	mouseOut: function(e) {
		e.stop();
		this.hide();
	}
});

var ToolTipManager = Class.create({
	initialize: function() {
		if (!document.loaded)
			Event.observe(window, 'load', this.documentLoaded.bindAsEventListener(this));
		else
			this.update(document.body);
	},
	documentLoaded: function(e) {
		this.update(document.body);
	},
	update: function(what) {
		var toolTipAnchors = $(what).select('.toolTip');
		toolTipAnchors.each(function(element){
			var existingHint = $('kasHint_' + element.identify());
			if (typeof existingHint == 'undefined' || existingHint == null)
				new HintToolTip(element);
		});
	}
});

var g_toolTipManager = new ToolTipManager();

var PopUpData = {
	basePosition: { top: 128, left: 160 },
	positionMultiple: { top: 32, left: 16 },
	numberOpen: 0,
	zIndex: 10000,
	shading: null
};

var PopUp = Class.create({
	initialize: function() {
		this.content = null;
		this.buttons = new Array();

		if (PopUpData.shading === null) {
			PopUpData.shading = new ModalBoxShading();
		}
		
		var div = this.divobject = new Element('div', { 'class': 'kasPopUp', 'style': 'display: none;' });
		div.appendChild(div = new Element('div', { 'class': 'topright' }));
		div.appendChild(div = new Element('div', { 'class': 'topleft' }));
		div.appendChild(this.divcontent = new Element('div'));
		div.appendChild(this.divbuttons = new Element('div', { 'class': 'buttons' }));
		this.divobject.appendChild(div = new Element('div',  { 'class': 'bottomright' }));
		div.appendChild(new Element('div', { 'class': 'bottomleft' }));

		// Make sure we are hidden
		this.divobject.hide();
		
		// Make position fixed to deal with scrolling docs...
		if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			this.divobject.style.position = 'absolute';
		}
		else {
			this.divobject.style.position = 'fixed';
		}

		// Add the divobject to the document body container
		document.body.appendChild(this.divobject);
	},
	setContent: function(content) {
		this.content = content;
		this.divcontent.update(this.content);
	},
	addButton: function(button) {
		this.buttons.push(button);
		this.divbuttons.appendChild(button);
	},
	checkFit: function(e) {
		// This isn't necessary on browser that don't support fixed because the user can scroll the window
		if (this.divobject.style.position != 'fixed')
			return;
		
		// Get the size of the viewport...
		var dimView = document.viewport.getDimensions();
		if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			dimView.width = Math.max(document.documentElement.clientWidth, document.body.clientWidth);
			dimView.height = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
		}
		
		// Get the size of ourself...
		var dimUs = this.divobject.getDimensions();
		var pos = this.divobject.cumulativeOffset();
		
		// Ok, figure out if we are NOT in view in any extent
		if (pos.left + dimUs.width > dimView.width ||
			pos.top + dimUs.height > dimView.height) {
			// Out of view in either the width or height, so re-center us in the view
			var left = Math.max(0, dimView.width / 2 - dimUs.width / 2);
			var top = Math.max(0, dimView.height / 2 - dimUs.height / 2);
			
			// See if we need to change either position
			if (pos.left != left || pos.top != top) {
				this.divobject.style.left = left + 'px';
				this.divobject.style.top = top + 'px';
			}
		}
	},
	show: function() {
		if (this.divobject.visible()) {
			return;
		}

		// Adjust the shading to cover everything below us and our our zIndex to make sure we are on top
		PopUpData.shading.setZIndex(PopUpData.zIndex);
		this.divobject.style.zIndex = PopUpData.zIndex + 1;
		PopUpData.zIndex += 2;
		PopUpData.numberOpen ++;
		PopUpData.shading.show();
		
		// Adjust our position
		var left, top;
		left = (PopUpData.basePosition.left + PopUpData.positionMultiple.left * (PopUpData.numberOpen - 1));
		top = (PopUpData.basePosition.top + PopUpData.positionMultiple.top * (PopUpData.numberOpen - 1));
		
		// Deal with older browsers (IE6 mostly) that don't understand position: fixed
		if (this.divobject.style.position == 'absolute') {
			var scrollPos = document.viewport.getScrollOffsets();
			left += scrollPos.left;
			top += scrollPos.top;
		}
		
		// Set our left, top attributes
		this.divobject.style.left = left + "px";
		this.divobject.style.top = top + "px";

		// Find every drop-down box that has a zIndex less than us that is visible and hide it if we are in IE6
		this.hiddenDropDowns = new Array();
		if (Prototype.Browser.IE && Prototype.Browser.Version < 7.0) {
			var dropdowns = Element.select(document, 'select', '[size="1"]');
			dropdowns.each(function (dropdown) {
				if (dropdown.visible() && dropdown.style.zIndex < this.divobject.style.zIndex) {
					dropdown.hide();
					this.hiddenDropDowns.push(dropdown);
				}
			}, this);
			var mydropdowns = Element.select(this.divobject, 'select', '[size="1"]');
			mydropdowns.each(function (dropdown) {
				if (this.hiddenDropDowns.indexOf(dropdown) >= 0) {
					dropdown.show();
					this.hiddenDropDowns = this.hiddenDropDowns.without(dropdown);
				}
			}, this);
		}
		
		// Show us
		this.divobject.style.visibility = 'visible';
		this.divobject.show();
		
		// Defer a check to make sure we are completely visible in the browser window.
		// Also run the check whenever the document is resized
		this.checkFit.bind(this).defer();
		this.checkFitEventHandler = this.checkFit.bindAsEventListener(this);
		Event.observe(window, 'resize', this.checkFitEventHandler);		
	},
	hide: function() {
		if (!this.divobject.visible()) {
			return;
		}
		this.hiddenDropDowns.each(function(dropdown) {
			dropdown.show();
		});
		delete this.hiddenDropDowns;
		Event.stopObserving(window, 'resize', this.checkFitEventHandler);
		this.divobject.hide();
		PopUpData.numberOpen --;
		PopUpData.zIndex -= 2;
		if (PopUpData.numberOpen == 0)
			PopUpData.shading.hide();
		PopUpData.shading.setZIndex(PopUpData.zIndex - 2);
	},
	visible: function() {
		return this.divobject.visible();
	}
});

var AlertPopUp = Class.create(PopUp, {
	initialize: function($super, message, callback) {
		$super();
		
		this.callback = (Object.isFunction(callback) ? callback : Prototype.emptyFunction);
		
		this.setContent(message);
		this.divcontent.style.marginTop = "50px";
		this.divcontent.style.marginBottom = "50px";
		this.addButton(this.okbutton = new Element('button', { 'class': 'kasBtn kasBtnGreen' }).update("Ok"));
		Event.observe(this.okbutton, 'click', this.clickOk.bindAsEventListener(this));
		this.divbuttons.style.marginLeft = "auto";
		this.divbuttons.style.marginRight = "auto";
		
		this.show();
		this.okbutton.focus();
	},
	clickOk: function(e) {
		this.hide();
		this.callback();
		this.divobject.remove();
	}
});

var WaitPopUp = Class.create(PopUp, {
	initialize: function($super) {
		$super();
		
		var image = new Element('img', { 'src': '/global/ajax/gui/images/gif/ajax-wait.gif' });
		this.setContent(image);
		this.divcontent.style.marginLeft = "auto";
		this.divcontent.style.marginRight = "auto";
		this.divcontent.style.marginTop = "50px";
		this.divcontent.style.marginBottom = "50px";
		this.divcontent.style.width = "16px";
		this.addButton(new Element('div').update("Please wait..."));

		this.timer = null;
		this.delay = 0;
	},
	clearDelayHide: function() {
		this.delay = 0;
	},
	delayShow: function(delay) {
		if (this.timer === null) {
			this.delay = delay;
			this.timer = setTimeout(this.show.bind(this), delay);
		}
	},
	show: function($super) {
		if (this.timer !== null) {
			clearTimeout(this.timer);
			this.timer = setTimeout(this.clearDelayHide.bind(this), this.delay);
		}
		$super();
	},
	delayHide: function(delay) {
		if (this.timer === null) {
			this.timer = setTimeout(this.hide.bind(this), delay);
		}
	},
	hide: function($super) {
		if (this.timer !== null) {
			clearTimeout(this.timer);
			this.timer = null;
			if (this.delay > 0) {
				this.delayHide(this.delay);
				this.clearDelayHide();
				return;
			}
		}
		$super();
	}
});

var Tab = Class.create({
	initialize: function(params, content) {
		if (content) {
			this.content = $(content);
		}
		else {
			this.content = new Element('div', Object.extend({ 'class': 'kasTabContent' }, params));
		}
		this.tab = null;
		this.index = null;
		this.description = null;
		this.manager = null;
		this.callback = this.defaultCallback.bind(this);
	},
	getContent: function() {
		return this.content;
	},
	appendChild: function(element) {
		return this.content.appendChild($(element));
	},
	getCallback: function() {
		return this.callback;
	},
	getTab: function(tab) {
		return this.tab;
	},
	setTabManager: function(manager) {
		this.manager = manager;
	},
	setIndex: function(index) {
		this.index = index;
	},
	setDescription: function(description) {
		if (description !== null) {
			if (this.tab !== null) {
				this.tab.update(description);
			}
			else {
				this.tab = new Element('li').update(element = new Element('a', {'href': '#'}).update(description));
			}
		}
		this.description = description;
	},
	setCallback: function(callback) {
		if (Object.isFunction(callback)) {
			this.callback = callback;
		}
	},
	setActive: function(active) {
		if (this.tab !== null) {
			if (active) {
				this.tab.addClassName('active');
			}
			else {
				this.tab.removeClassName('active');
			}
		}
	},
	defaultCallback: function(what) {
		if (what === "before-show") {
			return this.onBeforeShow();
		}
		else if (what === "show") {
			this.onShow();
		}
		else if (what === "before-hide") {
			return this.onBeforeHide();
		}
		else if (what === "hide") {
			this.onHide();
		}
		else {
			return false;
		}
	},
	show: function() {
		this.content.show();
	},
	hide: function() {
		this.content.hide();
	},
	visible: function() {
		return this.content.visible();
	},
	onBeforeShow: function() {
		return true;
	},
	onShow: function() {
	},
	onBeforeHide: function() {
		return true;
	},
	onHide: function() {
	}
});

var TabbedPopUp = Class.create(PopUp, {
	initialize: function($super) {
		$super();	
		this.tabs = new Array();
		this.divcontent.appendChild(this._tabs_element = new Element('ul', {'class': 'kasTabMenu'}));
		this.currentTab = -1;
	},
	clickTab: function(e, tabdata) {
		e.stop();
		this.showTab(tabdata.index);
	},
	addTab: function(description, content, callback) {
		if (content instanceof Tab) {
			var tabdata = content;
			content = tabdata.getContent();
		}
		else {
			var tabdata = new Tab({}, content);
		}
		tabdata.setTabManager(this);
		tabdata.setIndex(this.tabs.length);
		tabdata.setDescription(description);
		tabdata.setCallback(callback);
		tab = tabdata.getTab();
		if (tab !== null) {
			Event.observe(tab, 'click', this.clickTab.bindAsEventListener(this, tabdata));
			this._tabs_element.appendChild(tab);
		}
		tabdata.setActive(false);
		tabdata.hide();
		this.divcontent.appendChild(tabdata.getContent());
		this.tabs.push(tabdata);
	},
	showTab: function(index) {
		if (typeof index !== "number") {
			if (typeof index === "string") {
				tab = this.tabs.detect(function(tab) { return tab.description === index; });
				if ( typeof tab !== "undefined" ) {
					index = tab.index;
				}
			}
			if (typeof index !== "number") {
				return;
			}
		}
		if (this.currentTab != index) {
			if (this.currentTab >= 0) {
				if (this.tabs[this.currentTab].callback("before-hide") === false) {
					return;
				}
			}
			if (this.tabs[index].callback("before-show") === false) {
				return;
			}
			if (this.currentTab >= 0) {
				this.tabs[this.currentTab].hide();
				this.tabs[this.currentTab].setActive(false);
				this.tabs[this.currentTab].callback("hide");
			}
		}
		else {
			if (this.tabs[index].callback("before-show") === false) {
				return;
			}
		}
		this.tabs[index].setActive(true);
		this.tabs[index].show();
		this.tabs[index].callback("show");
		this.currentTab = index;
	},
	hide: function($super) {
		if (this.currentTab > -1 && this.currentTab < this.tabs.length) {
			if (this.tabs[this.currentTab].callback("before-hide") === false)
				return;
			this.tabs[this.currentTab].callback("hide");
			this.tabs[this.currentTab].hide();
		}
		$super();
	}
});

var g_kasTinyMCELoader = null;
var KasTinyMCELoader = Class.create(PopUp, {
        initialize: function(tinymcereadycallback) {
                if (g_kasTinyMCELoader == null) {
                        g_kasTinyMCELoader = this;

                        this.tinyMCEloaded = false;
                        this.callbacks = new Array();
                        if (typeof tinymcereadycallback == 'function')
                                this.callbacks.push(tinymcereadycallback);

                        if (typeof tinyMCE === "undefined") {
                                var scriptTag = new Element('script', {'language': 'Javascript', 'src': '/global/javascript/tiny_mce/3.3.9.3/tiny_mce/tiny_mce.js'});
                                Event.observe(scriptTag, 'load', this.tinyMCELoadedCallback.bindAsEventListener(this));
                                __setCSS_Helper(scriptTag);
                        }
                        else
                                this.tinyMCELoadedCallback(null);
                }
                else {
                        if (typeof tinymcereadycallback == 'function') {
                                if (g_kasTinyMCELoader.tinyMCEloaded)
                                        tinymcereadycallback();
                                else
                                        g_kasTinyMCELoader.callbacks.push(tinymcereadycallback);
                        }
                }
        },
        tinyMCELoadedCallback: function(e) {
                if (e != null)
                        e.stop();
                this.tinyMCEloaded = true;
                this.callbacks.each(function (f) {f();});
        }
});

// create CSS element on the fly
function __setCSS_Helper(css) {
	try {
		// append stylesheet to alter
		document.getElementsByTagName("head")[0].appendChild(css);
	} catch (e) {
		setTimeout(function(){__setCSS_Helper(css)}, 100);
	}
}

function _setCSS() {
	var css = new Element('link', { 'href': '/global/ajax/gui/gui.css', 'rel': 'stylesheet', 'type': 'text/css' });
	
	// attempt to add the css and then keep trying till we do
	__setCSS_Helper(css);
	css = null;
}

// _setCSS();


