if (typeof Prototype == 'undefined' || !(Prototype.Version.match("1.6") || Prototype.Version.match("1.7")))
	throw ("GlobalEagle-GUI library requires Prototype library >= 1.6.0");
if (typeof jQuery == 'undefined')
	throw ("GlobalEagle-GUI library requires jQuery library");

Object.extend(GUI, {
	TabsElement: Class.create({ // Represents multiple tabs, nav and pane section.
		initialize: function (id) {
			this.element = $(id); // Maybe undefined;
		},
		getTabContext: function (tabContext) {
			try {
				if (!tabContext) return;
				if (tabContext.wmElement !== undefined) {
					var wmElement = tabContext.wmElement;
					wmElement = Object.isNumber(wmElement) ? $("wm-" + parseInt(wmElement)) : $(wmElement); // 09.11.2009 Ossig wmElement: workLevelIndex, wm container id, wm container.
					var tabPaneElement = wmElement.up("div");
					var tabPaneID = $_id(tabPaneElement);
					var tabsElement = wmElement.up(".ui-tabs");
					// var tabID = $_id(tabsElement);
					var tabsNavElement = tabsElement.down("ul");
					var liElementArr = tabsNavElement.select("li");
					var liElement = tabsNavElement.down("a[href=#" + tabPaneID + "]").up("li");
					var tabIndex = liElementArr.indexOf(liElement);
					return { tabsElement: tabsElement, tabIndex: tabIndex, tabPaneElement: tabPaneElement, tabNavElement: liElement, wmElement: wmElement };
				} else if (this.element || tabContext.tabsElement) {
					GUI.assert(!tabContext.tabsElement || tabContext.tabsElement === this.element, "getTabContext"); // Maybe only for workLevel.
					var tabsElement = tabContext.tabsElement ? $(tabContext.tabsElement) : this.element;
					if (tabContext.tabIndex !== undefined) {
						var tabIndex = parseInt(tabContext.tabIndex);
						var tabsNavElement = tabsElement.down("ul");
						var liElementArr = tabsNavElement.select("li");
						var liElement = liElementArr[tabIndex];
						var hRef = liElement.down("a").readAttribute("href");
						// var tabPane = $$(hRef)[0];
						var tabPaneElement = $(hRef.substr(1));
						var wmElement = tabPaneElement.down("div");
						return { tabsElement: tabsElement, tabIndex: tabIndex, tabPaneElement: tabPaneElement, tabNavElement: liElement, wmElement: wmElement };
					} else if (tabContext.tabNavElement && tabContext.tabPaneElement) {
						function getElementIndex(element) {
							var elementList = element.up().select(element.tagName);
							return elementList.indexOf(element);
						}
						var liElement = tabContext.tabNavElement;
						var tabIndex = getElementIndex(liElement);
						GUI.assert(tabIndex >= 0, "getTabContext");
						if (tabIndex < 0) return;
						var tabPaneElement = tabContext.tabPaneElement;
						var wmElement = tabPaneElement.down("div");
						return {tabsElement: tabsElement, tabIndex: tabIndex, tabPaneElement: tabPaneElement, tabNavElement: liElement, wmElement: wmElement };
					}
				} else
					return;
			} catch (ex) {
				return;
			}
		}
	})
});
Object.extend(GUI, {
	Tabs: Class.create(GUI.TabsElement, { // "WorkFrameTab", "WorkFrameTab-"
		initialize: function ($super, tabsID, panePrefix, workLevelClassName) {
			$super(tabsID);
			var tabsElement = this.element;
			if (!jQuery.fn.tabs)
				throw ("GlobalEagle-GUI library requires jQuery tabs");
			this._onResizeList = [];
			this._onRemoveList = [];
			this._onSelectList = [];
			// tabs init with a custom tab template and an "add" callback filling in the content
			// this._tabsID = tabsID;
			this._onSelectEvent = this._onSelect.bind(this);
			tabsElement.addClassName(workLevelClassName);
			this.navElement = tabsElement.down("ul");
			this._panePrefix = panePrefix;
			this._selectedTabIndex = 0;
			var that = this;
			// var jTabs = $j("#" + $_id(tabsElement))
			var jTabs = $j(tabsElement)
				.tabs({
					// tabTemplate: '<li><div style="position: relative;"><a href="#{href}">#{label}</a> <span class="ui-icon ui-icon-close">Remove Tab</span></div></li>',
					// tabTemplate: '<li><a href="#{href}">#{label}</a><span class="ge-tab-close ui-icon ui-icon-close ' + workLevelClassName + '">Remove Tab</span><a href="#" class="ge-minisymbol ge-minisymbol-close ' + workLevelClassName + '"></a><a href="#" class="ge-minisymbol ge-minisymbol-closeunselected ' + workLevelClassName + '"></a></li>',
					tabTemplate: '<li><a href="#{href}">#{label}</a><a href="#" class="ge-tab-close ge-minisymbol ge-minisymbol-close ' + workLevelClassName + '"></a><a href="#" class="ge-tab-close ge-minisymbol ge-minisymbol-closeunselected ' + workLevelClassName + '"></a></li>',
					/* add: function(event, ui) { // 22.10.2009 Ossig Already added, just notification
					// var wmContainer = new Element("div", { "id": "wmTest-" + tab_counter });
					// $(ui.panel).insert(wmContainer);
					// var workLevelIndex = GUI.metaWM.registerWorkLevel(ui.panel);
					// that._workLevelIndex = workLevelIndex;

					// var tab_content = 'Tab ' + tab_counter + ' content.' // + tab_content2;
					// $j(ui.panel).append('<p>' + tab_content + '</p>');
					$j(this).tabs('select', '#' + ui.panel.id); // 10.11.2009 Ossig Assumed wm child already exists, which does not.
					}, */
					select: function (event, ui) {
						var tabs = that;
						// tabs._onSelectList.invoke("curry", ui.index).invoke("call"); // 10.11.2009 Ossig Still not selected - pane invisible.
						// tabs._onSelectEvent.defer(ui.index); // 03.07.2011 Ossig ui.index is relative but not absolute by sortable. inserting works absolute.
						var tabContext = tabs.getTabContext({
							tabNavElement: ui.tab.up("li"),
							tabPaneElement: ui.panel
						});
						tabs._selectedTabIndex = tabContext.tabIndex;
						if (tabContext) tabs._onSelectEvent.defer(tabContext.tabIndex);
					}
				});
			jTabs.find("> .ui-tabs-nav").sortable({
				axis: "x",
				update: function (event, ui) {
					that._sortUpdate = true;
				}
			}); // {placeholder: "sortableplaceholder" , cancel: "a"}
			// close icon: removing the tab on click
			// note: closable tabs gonna be an option in the future - see http://dev.jqueryui.com/ticket/3924
			// $j('#tabs span.ui-icon-close').live('click', function() {
			// var jTabs1 = $j("#" + $_id(tabsElement));
			// var jTabs2 = $j(tabsElement);
			// $j("> ul > li > .ge-tab-close", jTabs1).live("click", function () { // 04.11.2009 Ossig this == close button
			$j("#" + $_id(tabsElement) + " > ul > li > .ge-tab-close").live("click", function () { // 04.11.2009 Ossig this == close button // 03.07.2011 Ossig Not available in the moment of calling.
				var tabs = that;
				GUI.log(".ge-tab-close onClick");
				var jButton = $j(this);
				var indexClicked = $j(" > ul > li", jTabs).index(jButton.parent()); // 04.11.2009 Ossig List of "li" EINEM "li" gegenübergestellt.
				/* 04.11.2009 Ossig Does not work together with sortable.
				var indexSelected = jTabs.tabs("option", "selected"); // 22.10.2009 Ossig
				if (indexClicked != indexSelected) return; // 04.11.2009 Ossig Ignore close nonselected tab.
				*/
				// var indexClicked = jTabs.tabs("option", "selected");
				// var indexClicked = tabs._selectedTabIndex;
				tabs._onRemoveList.invoke("curry", indexClicked).invoke("call");
				// tabs._onRemoveList.invoke("call", indexClicked, tabs._sortUpdate);
			}).live("mousedown", function () {
				GUI.log(".ge-tab-close onMouseDown");
				var button = $(this);
				button.addClassName("ge-state-active");
			}).live("mouseup", function () {
				GUI.log(".ge-tab-close onMouseUp");
				var button = $(this);
				button.removeClassName("ge-state-active");
			});
			/*
			$j("> ul > li > .ge-minisymbol-close", jTabs).live("mousedown", function() { // 04.11.2009 Ossig this == close button
			var button = $(this);
			button.addClassName("ge-state-active");
			}).live("mouseup", function() {
			var button = $(this);
			button.removeClassName("ge-state-active");
			});
			*/
			/*
			function addTab() {
			var tab_title = 'Tab ' + tab_counter;
			jTabs.tabs('add', "#" + panePrefix + tab_counter, tab_title, 0);
			tab_counter++;
			}
			addTab();
			addTab();
			addTab();
			*/
		},
		_onSplitterPaneResize: function (splitterPane) {
			// var areaInner = jPane.innerHeight();
			// var areaOuter = jPane.outerHeight();
			// tabsElement.style.height = area.height - 3 * 2 + "px";
			var area = splitterPane.element.getDimensions();
			// this.element.setSize({ height: area.height });
			this.log("setSize {width:", area.width, ", height:", area.height, "} by splitterPane");
			this.element.setOuterSize(area);
			this._onResizeList.invoke("call");
		},
		_onTabsResize: function (workLevelTabs) {
			var area = workLevelTabs.getVisiblePaneSize(); // 03.01.2011 area == undefined when invisible.
			// this.element.setSize({ height: area.height });
			if (area) this.log("setSize {width:", area.width, ", height:", area.height, "} by tabs");
			// this.element.setSize(area.width, area.height); // 18.11.2009 Ossig Not correct. To be done by metaWindowManager triggered below.
			this._onResizeList.invoke("call");
		},
		/* _onTabsRemove: function(tabs, tabIndex) {
		this.log("onTabsRemove: ", $_id(tabs.element), "[", tabIndex, "]");
		this.comLinkArr.invoke("stop");
		this.comLinkArr = undefined;
		tabs.remove(tabIndex);
		}, */
		log: function (arg) {
			GUI.log.apply(GUI, ["Tabs ", $_id(this.element), ": "].concat($A(arguments))); // 20.09.2009 Ossig Übergibt Argumente.
		},
		_onSelect: function (tabIndex) {
			this._onSelectList.invoke("curry", tabIndex).invoke("call"); // 10.11.2009 Ossig destination pane required to be visible/selected.
		},
		addWorkLevel: function (workLevel, tabNavOpt) {
			// var tabsID = this._tabsID;
			var panePrefix = this._panePrefix;
			var panePostfix = workLevel.frameIndex;
			function getTabName(tabName) {
				return tabName ? tabName : "Tab" + panePostfix;
			}
			if (!tabNavOpt)
				tabNavOpt = { tabName: getTabName(), tabIndex: 0 }
			else if (Object.isString(tabNavOpt))
				tabNavOpt = { tabName: tabNavOpt, tabIndex: 0 }; // @@@ tabIndex: 1, but 1 has to exist.
			// 21.12.2009 Ossig tabIndex===undefined: append to the end.

			// var tabsID = $_id(this.element);
			var navTitle = getTabName(tabNavOpt.tabName);
			var jTabs = $j(this.element);
			var paneID = panePrefix + panePostfix;
			var tabIndex = tabNavOpt.tabIndex;
			if (Object.isUndefined(tabIndex)) tabIndex = jTabs.tabs("length");
			jTabs.tabs("add", "#" + paneID, navTitle, tabIndex);
			// return { tabsElement: this.element, tabIndex: tabIndex, tabPaneElement: $(paneID) };
			return this.getTabContext({ tabIndex: tabIndex });
		},
		observeResize: function (onResize) {
			this._onResizeList.push(onResize);
		},
		stopObservingResize: function (onResize) {
			this._onResizeList = this._onResizeList.findAll(function (_onResize) {
				return _onResize != onResize;
			});
		},
		observeRemove: function (onRemove) {
			this._onRemoveList.push(onRemove);
		},
		stopObservingRemove: function (onRemove) {
			this._onRemoveList = this._onRemoveList.findAll(function (_onRemoveList) {
				return _onRemoveList != onRemove;
			});
		},
		observeSelect: function (onSelect) {
			this._onSelectList.push(onSelect);
		},
		stopObservingSelect: function (onSelect) {
			this._onSelectList = this._onSelectList.findAll(function (_onSelectList) {
				return _onSelectList != onSelect;
			});
		},
		remove: function (tabIndex) {
			GUI.log("tab remove", tabIndex);
			var jTabs = $j(this.element);
			// jTabs.tabs("remove", tabIndex);
			/*
			var paneIndex = this._getPaneIndex(tabIndex); // 16.11.2009 Ossig Workaround sortable error.
			jTabs.tabs("remove", paneIndex);
			*/

			if (!this._sortUpdate) {
				jTabs.tabs("remove", tabIndex); // 20.07.2011 Google "jquery tabs sortable remove": http://forum.jquery.com/topic/remove-sortable-tabs
			} else {
				var tabContext = this.getTabContext({ tabIndex: tabIndex });
				$(tabContext.tabNavElement).remove();
				$(tabContext.tabPaneElement).remove();
			}
			if (jTabs.tabs("length") == 0) this._sortUpdate = false;
			return this;
		},
		rename: function (tabIndex, name) {
			// var jTabs = $j("#" + $_id(this.element));
			var tabContext = this.getTabContext({ tabIndex: tabIndex });
			var tabNavElement = tabContext.tabNavElement;
			var nameElement = tabNavElement.down("a");
			// var oldName = nameElement.innerHTML;
			nameElement.update(name);
			return this;
		},
		select: function (tabIndex) {
			GUI.log("tab select", tabIndex);
			var jTabs = $j(this.element);
			// jTabs.tabs("select", tabIndex);
			/*
			var paneIndex = this._getPaneIndex(tabIndex); // 16.11.2009 Ossig Workaround sortable error.
			jTabs.tabs("select", paneIndex);
			*/
			jTabs.tabs("select", tabIndex);
			return this;
		},
		tabLength: function () {
			/*
			var jTabs = $j("#" + $_id(this.element));
			return jTabs.tabs("length");
			*/
			return $j(this.element).tabs("length");
		},
		getVisiblePaneSize: function (tabContext) {
			var tabsElement = this.element;
			var tabPaneElement;
			if (!tabContext)
				tabPaneElement = this._getActivePaneElement();
			else if (tabContext.tabPaneElement)
				tabPaneElement = tabContext.tabPaneElement;
			else if (tabContext.wmElement)
				tabPaneElement = tabContext.wmElement.up("div");
			else {
				tabContext = this.getTabContext(tabContext);
				tabPaneElement = tabContext.tabPaneElement;
			}
			if (!tabPaneElement) return;
			// if (!tabPane.visible()) return; // 03.11.2009 Ossig Does not work for css induced visibility (css limitation). But as noticable in Firebug ....
			GUI.log("getVisiblePaneSize:", tabPaneElement);
			if (tabPaneElement.hasClassName("ui-tabs-hide")) return; // 17.04.2010 Ossig Invisible or out of screen.
			var sizePane = tabPaneElement.getDimensions();
			if (sizePane.height <= 0 || sizePane.width <= 0) return; // 03.11.2009 Ossig !visible, !selected // 18.03.2010 Ossig Maybe < 0

			// var size = tabsElement.getDimensions();
			var offsetTabs = tabsElement.positionedOffset(); // 11.11.2009 Ossig Hierarchical tabs.
			var offsetPane = tabPaneElement.positionedOffset();
			var offsetSize = tabPaneElement.getDimensions();
			// var frameSize1 = tabsElement.getFrameSize({ width: 0, height: 0 });
			// var frameSize2 = tabPaneElement.getFrameSize({ width: 0, height: 0 });
			/* return {
			width: offsetSize.width - frameSize1.width - frameSize2.width,
			height: size.height - offsetPane.top + offsetTabs.top - frameSize1.height - frameSize2.height
			}; */
			var innerSize = {
				width: tabsElement.clientWidth, // offsetSize.width,
				height: tabsElement.clientHeight - offsetPane.top + offsetTabs.top,
				tabPaneElement: tabPaneElement
			};
			innerSize = innerSize.height > 0 && innerSize.width > 0 ? innerSize : undefined;
			GUI.log("getVisiblePaneSize =", innerSize);
			return innerSize;
		} /* ,
		_getPaneIndex: function (tabIndex) {
			// 16.11.2009 Ossig Workaround Error in jQuery-ui 1.7.2 ==> Fix announced for 1.8. http://dev.jqueryui.com/ticket/4524
			// 24.07.2011 Ossig Fix only available for select.
			var tabContext = tab.getTabContext({ tabIndex: tabIndex });
			var paneElementArr = tabContext.tabsElement.childElements().findAll(function (element) {
				return element.tagName.toLowerCase() == "div";
			});
			var paneIndex = paneElementArr.indexOf(tabContext.tabPaneElement);
			return paneIndex;
		}
		*/
	}),
	Splitter: Class.create({
		// _onResizeList: [], 11.11.2009 Ossig class member
		initialize: function (splitterID) {
			if (!jQuery.fn.splitter)
				throw ("GlobalEagle-GUI library requires jQuery splitter");
			this._onResizeList = [];
			this._splitterID = splitterID;
			var jSplitter = $j("#" + splitterID);
			// jSplitter.offset(0, 0);
			// jSplitter.position(0, 0);
			jSplitter.splitter({
				type: "v",
				outline: true,
				// minLeft: 100, sizeLeft: 250, minRight: 100,
				minLeft: 250, sizeLeft: 250, maxLeft: 300,
				dock: "left", dockSpeed: 300, resizeToWidth: true,
				/* resizeToWidth: true, */
				anchorToWindow: true
				// cookie: "vsplitter", // 27.10.2009 Ossig clientside profile!
				// accessKey: 'I'
			});
			/*
			jSplitter.splitter({
			type: "v",
			outline: true,
			sizeLeft: 150,
			minLeft: 100,
			minRight: 100,
			resizeToWidth: true,
			dock: "left", // dock: "right",
			dockSpeed: 200,
			// cookie: "docksplitter",
			dockKey: 'Z', // Alt-Shift-Z in FF/IE
			accessKey: 'I', // Alt-Shift-I in FF/IE 
			anchorToWindow: true
			});
			*/
			jSplitter.bind("resize", this._onResize.bind(this));
			// jSplitter.unbind("resize");
		} /*,
		_onResize: function(jEvent) {
			var pane = jEvent.data.pane;
			if (pane && jEvent.target != pane) return;
			var onResize = jEvent.data.onResize;
			onResize();
		}*/,
		_onResize: function (jEvent) {
			var target = jEvent.target;
			var dataList = this._onResizeList.findAll(function (data) {
				var pane = data.pane;
				return !pane || pane == target;
			});
			dataList.invoke("onResize");
		},
		observeResize: function (pane, onResize) {
			var data = { onResize: onResize, pane: $(pane) };
			this._onResizeList.push(data);
		},
		stopObservingResize: function (onResize) {
			this._onResizeList = this._dataList.findAll(function (data) {
				return data.onResize != onResize;
			});
		}
	}),
	SplitterPane: Class.create({
		initialize: function (splitter, paneElement) {
			splitter = $(splitter);
			paneElement = $(paneElement);
			this.splitter = splitter;
			this.element = paneElement;
			this.stopObservingResize = splitter.stopObservingResize.bind(splitter);
		},
		observeResize: function (onResize) {
			return this.splitter.observeResize(this.element, onResize);
		}
	})
});

/*
Object.extend(GUI.WindowManager.prototype, (function() {
	var resizeIndex = 0;
	function resize() {
		GUI.log("GUI.WindowManager.resize also in inheritance chain. resizeIndex=", resizeIndex++);
	}
	return {
		resize: resize
	}
})());
*/

Object.extend(GUI, {
	WorkLevelTabs: Class.create(GUI.Tabs, { // "WorkLevelTab", "WorkLevelTab-"
		initialize: function ($super, tabsID, panePrefix) {
			$super(tabsID, panePrefix, "ge-level");
		},
		_getActivePaneElement: function () {
			return this.element.select(".ui-tabs-panel:not(.ui-tabs-hide) .ui-tabs").first().up(".ui-tabs-panel"); // 11.11.2009 Ossig WorkFrameTabsElement child of WorkLevelTabsElement. // 17.11.2009 Ossig wm div between.
		},
		registerWorkPane: function (splitterPane) {
			new GUI.ComLink({ observer: splitterPane, oFn: "observeResize", oStopFn: "stopObservingResize", receiver: this, rFn: "_onSplitterPaneResize" }).trigger();
			return this;
		}
	}),
	WorkFrameTabs: Class.create(GUI.Tabs, { // "WorkFrameTab", "WorkFrameTab-"
		initialize: function ($super, tabsID, panePrefix) {
			$super(tabsID, panePrefix, "ge-frame");
		},
		_getActivePaneElement: function () {
			return this.element.select(".ui-tabs-panel:not(.ui-tabs-hide)").first();
		},
		registerWorkPane: function (workLevelTabs) {
			new GUI.ComLink({ observer: workLevelTabs, oFn: "observeResize", oStopFn: "stopObservingResize", receiver: this, rFn: "_onTabsResize" }).trigger();
			// new GUI.ComLink({ observer: workLevelTabs, oFn: "observeRemove", oStopFn: "stopObservingRemove", receiver: this, rFn: "_onTabsRemove" }); // 13.11.2009 Ossig Managed by MetaWindowManager
			return this;
		}
	})
});

