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, {
	Tabs: Class.create({ // "WorkFrameTab", "WorkFrameTab-"
		/*
		_onResizeList: [], // class member
		_onRemoveList: [], // class member
		_onSelectList: [], // class member
		*/
		initialize: function(tabsElement, panePrefix, workLevelClassName) {
			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);
			var tabs = $(tabsElement);
			this.element = tabs;
			tabs.addClassName(workLevelClassName);
			this.navElement = tabs.down("ul");
			this._panePrefix = panePrefix;
			var that = this;
			var jTabs = $j("#" + $_id(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 tab = that;
						// tab._onSelectList.invoke("curry", ui.index).invoke("call"); // 10.11.2009 Ossig Still not selected - pane invisible.
						tab._onSelectEvent.defer(ui.index);
					}
				})
			jTabs.find("> .ui-tabs-nav").sortable({ axis: "x" }); // {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() {
			$j("> ul > li > .ge-tab-close", jTabs).live("click", function() { // 04.11.2009 Ossig this == close button
				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.
				*/
				that._onRemoveList.invoke("curry", indexClicked).invoke("call");
			}).live("mousedown", function() {
				var button = $(this);
				button.addClassName("ge-state-active");
			}).live("mouseup", function() {
				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();
			// this.element.setSize({ height: area.height });
			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 };
			// 21.12.2009 Ossig tabIndex===undefined: append to the end.

			var tabsID = $_id(this.element);
			var navTitle = getTabName(tabNavOpt.tabName);
			var jTabs = $j("#" + tabsID);
			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) {
			var jTabs = $j("#" + $_id(this.element));
			// jTabs.tabs("remove", tabIndex);
			var paneIndex = this._getPaneIndex(tabIndex); // 16.11.2009 Ossig Workaround sortable error.
			jTabs.tabs("remove", paneIndex);
			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) {
			var jTabs = $j("#" + $_id(this.element));
			// jTabs.tabs("select", tabIndex);
			var paneIndex = this._getPaneIndex(tabIndex); // 16.11.2009 Ossig Workaround sortable error.
			jTabs.tabs("select", paneIndex);
			return this;
		},
		length: function() {
			var jTabs = $j("#" + $_id(this.element));
			return jTabs.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;
		},
		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 (tabContext.tabIndex != undefined) {
					var tabIndex = parseInt(tabContext.tabIndex);
					var tabsElement = tabContext.tabsElement ? $(tabContext.tabsElement) : this.element;
					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 };
				}
			} catch (ex) {
				return;
			}
		},
		_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
			var tabContext = this.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,
				/* resizeToWidth: true, */
				anchorToWindow: true
				// cookie: "vsplitter", // 27.10.2009 Ossig clientside profile!
				// accessKey: 'I'
			});
			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;
		}
	})
});
