/**
 * The javascripts functions for Naris tab
 * @author Ozgur Ayten
 */

var Akyla_Prototype_Widget_Tabs = Class.create(Akyla_Prototype_Observer,
{
	/**
	 * Name of the module 
	 */
	moduleName : "Akyla.Widget.Tabs",
	/**
	 * Load default preferences for the JSON  Table
	 */
	loadDefaultPreferences : function()
	{
		this.preferences = 
		{
		}
	},
	/**
	 * Processes a JSON component. In this cases it @use this.buildTable
	 * @param object component JSON component to process
	 */
	processComponent : function (component, requestOptions, data)
	{
		var akylaTab = $(component.containerId).akylaTab;
		if (!akylaTab && $(component.containerId).hasClassName("akylaTab"))
		{
			akylaTab = new Akyla_Prototype_Widget_Tab($(component.containerId));
		}
		if (akylaTab != null)
		{
			if (component.operation == "default")
			{
				akylaTab.add(component.objectId, {titles : component.titles, contents : component.contents, overlayEnabled : data.overlayEnabled});
			}
			else if (component.operation == "select")
			{
				akylaTab.setActiveTab(component.objectId);
			}
			else if (component.operation == "remove")
			{
				akylaTab.remove(component.objectId);
			}
		}
	},
	loadTabAsync : function(tabList,index)
	{
		if (tabList.size() < 1)
		{
			return;
		}
		setTimeout(function ()
		{
			var element = $(tabList[index]);
			if (!element || element.hasClassName("processed"))
			{
				return;
			}
			element.addClassName("processed");
			new Akyla_Prototype_Widget_Tab(element);
			var next = index+1;
			if (next < tabList.size())
			{
				this.loadTabAsync(tabList,next);
			}
		}.bind(this),0);
	},
	initTabs : function (container)
	{
		$(container).select(".akylaTab").each(function (element)
		{
			if (element && !element.hasClassName("processed"))
			{
				element.addClassName("processed");
				new Akyla_Prototype_Widget_Tab(element);	
			}
		}.bind(this));
	},
	initTabsAsync : function (container)
	{
		var tabList = $(container).select(".akylaTab");
		if (!tabList || tabList.size() < 1)
		{
			return;
		}
		this.loadTabAsync(tabList,0);
	},
	domLoaded : function()
	{
		//observe the AkylaTab.js when window load
		this.initTabs(document.body);
		Event.observe(document,"container:change", function (event)
		{
			this.initTabs(event.target);
		}.bind(this));		
	}
});

/**
 * Instantiate the Tabs Widget
 */
Akyla.Widget.Tabs = new Akyla_Prototype_Widget_Tabs();

/**
 * Akyla_Prototype_Widget_Tab
 *
 * Creates tab navigation
 */
var Akyla_Prototype_Widget_Tab = Class.create(
{
	initialize : function(tabElement, preferences)
	{
		this.tabElement = $(tabElement);
		if (!this.tabElement)
		{
			return;
		}
		this.activeTab = null; // List tab = first tab
		this.tabElement.akylaTab = this;
		this.tabCount = 0;
		this.tabTitle = null;
		this.executors = $H();
		this.hideAkylaTabList = false;
		this.loadDefaultPreferences();
		/*
		 * objectId attribute should hold which object a tab or tabtitle is linked to
		 */
		/* Each buttons should correspond to an object ID which in turn can be used to identify the
		 * content which should be shown
		 */
		this.titleSelectors = new Hash(); // more than 1 row of buttons. Every title should have an id like : objectTabWidget_0_1
		this.titleSelectors.set("main","#"+this.tabElement.identify()+" .titles li.title");

		this.contentSelectors = new Hash(); // more contents for 1 button
		this.contentSelectors.set("main","#"+this.tabElement.identify()+" .contents div.content");

		/*
		 * TODO : actually use these preferences
		 */
		this.preferences = Object.extend(this.preferences, preferences);
		this.preferences.scrollButtons = !this.tabElement.hasClassName("hideScrollButtons");
		this.preferences.previewPaned = this.tabElement.hasClassName("previewPaned");
		/*
		 * Setup extra title selectors if these were set
		 */
		var titleSelectors = this.tabElement.readAttribute("extratitleselectors");//.gsub("\'","\"");
		if (titleSelectors != null)
		{
			titleSelectors = titleSelectors.gsub("'","\"");
			titleSelectors = titleSelectors.evalJSON();
			$H(titleSelectors).each(function (titleSelector)
			{
				this.titleSelectors.set(titleSelector.key,titleSelector.value);
			}.bind(this));
		}
		/*
		 * Setup extra content selectors if these were set
		 */
		var contentSelectors = this.tabElement.readAttribute("extracontentselectors");//.gsub("\'","\"");
		if (contentSelectors != null)
		{
			contentSelectors = contentSelectors.gsub("'","\"");
			contentSelectors = contentSelectors.evalJSON();
			$H(contentSelectors).each(function (contentSelector)
			{
				this.contentSelectors.set(contentSelector.key,contentSelector.value);
			}.bind(this));
		}

		// Hide not selected contents
		this.contentSelectors.each(function (pair)
		{
			var index = 0;
			$$(pair.value).each(function (content)
			{
				$(content).writeAttribute("objectId",index);
				if (index > 0)
				{
					content.hide();
				}
				if (index == 0 && this.preferences.previewPaned)
				{
					content.addClassName("previewPane");
				}
				index++;
			}.bind(this));
		}.bind(this));

		// Set up titles
		this.titleSelectors.each(function (pair)
		{
			// Observe the titles
			var titles = $$(pair.value);
			if (titles.size() == 0)
			{
				return;
			}
			titles.first().up().observe("click", function (event) 
			{
				var target = event.target;
				if (target.tagName.toLowerCase() == "img" && target.hasClassName("closeButton"))
				{
					if (target.up("li") != null)
					{
						if (event.shiftKey)
						{
							this.remove($(target.up("li")).readAttribute("objectid"),true);
						}
						else
						{
							this.remove($(target.up("li")).readAttribute("objectid"));
						}
						Event.stop(event);
					}
				}
				if (target.up("li") != null)
				{
					this.setActiveTab(target.up("li").readAttribute("objectid"));
					Event.stop(event);
				}
			}.bind(this));
			var index = 0;
			if (!titles.first().up().visible())
			{
				titles.first().up().setStyle({height : titles.first().up().getHeight()+"px"});
			}
			if (pair.key == "main")
			{
				this.tabTitle = titles.first().up();
			}
			titles.each(function (title)
			{
				// WIDTH
				if (pair.key == "main")
				{
					this.tabCount++;
				}
				title = $(title);
				title.writeAttribute("objectid",index);
				// Hidden buttons are hidden
				if (title.hasClassName("hidden"))
				{
					title.hide();
					title.removeClassName("hidden");
				}

				// Add close button to tabs which one want
				if (title.hasClassName("closable"))
				{
					title.down("span").insert({bottom : this.createCloseButton()});
				}
				index++;
			}.bind(this));	
		}.bind(this));

		var activeTitle = $$(this.titleSelectors.get("main")+".active").first();
		if (activeTitle != null)
		{
			this.preferences.defaultActiveTab = activeTitle.readAttribute("objectid");
		}
		/*
		 * Set active tab to the defaulttab
		 */
		this.setActiveTab(this.preferences.defaultActiveTab);
		// TODO : scrollbuttons
		if (this.preferences.scrollButtons)
		{
			this.createScrollButtons(); 
		}
		if (this.preferences.previewPaned)
		{
			var firstTab = $$(this.titleSelectors.get("main")).first();
			var title = firstTab.down("span").innerHTML;
			firstTab.hide();
			var header = new Element("h2").update(title);
			$$(this.contentSelectors.get("main")).first().insert({top : header});
		}
		this.afterInit();
	},
	afterInit : function ()
	{
	},
	loadDefaultPreferences : function()
	{
		this.preferences = 
			{
				activeClassName : "active",
				defaultActiveTab : 0,
				previewPaned : false,
				scrollButtons : true,
				scrollButtonsRight : false,
				alwaysActivateNewTabs : false
			};
	},
	getTotalTitleWidth : function()
	{
		var totalWidth = 0;
		var lastElement = $$(this.titleSelectors.get("main")).last();

		totalWidth += lastElement.positionedOffset()[0] + lastElement.getWidth() ;
		return totalWidth;
	},
	createScrollButtons : function()
	{
		if (!this || !this.tabElement || !this.tabElement.down(".titles"))
		{
			return;
		}
		var titleHeight = this.tabElement.down(".titles").getHeight();
		if (!titleHeight)
		{
			titleHeight = 27;
		}
		else
		{
			titleHeight--;
		}
		var image = new Element("img", {src : Akyla.preferences.baseUrl+"/image/gfx/tabs/previous.png"});
		var leftArrow = new Element("button", {style : "cursor : pointer" }).insert({bottom : image});
		var image = new Element("img", {src : Akyla.preferences.baseUrl+"/image/gfx/tabs/next.png"});
		var rightArrow = new Element("button", {style : "cursor : pointer;" }).insert({bottom : image});
		var image = new Element("img", {src : Akyla.preferences.baseUrl+"/image/gfx/tabs/tabList.png"});
		var listArrow = new Element("button", {style : "cursor : pointer;" }).insert({bottom : image});
		var rightCurtain = new Element("div").setStyle({position : "absolute", right : "0px", top : "0px", height : titleHeight+"px"}).addClassName("buttonCurtain");
		var leftCurtain = new Element("div").setStyle({position : "absolute", left : "0px", top : "0px", height : titleHeight+"px"}).addClassName("buttonCurtain");
		if (this.preferences.previewPaned)
		{
			leftCurtain.setStyle({width : "250px"});
		}
		if (this.preferences.scrollButtonsRight)
		{
			rightCurtain.insert({bottom : leftArrow});
			rightCurtain.insert({bottom : rightArrow});
			rightCurtain.insert({bottom : listArrow});
			this.tabElement.insert({bottom : rightCurtain});
		}
		else
		{
			leftCurtain.insert({bottom : leftArrow});
			rightCurtain.insert({bottom : rightArrow});
			rightCurtain.insert({bottom : listArrow});
			this.tabElement.insert({bottom : leftCurtain});
			this.tabElement.insert({bottom : rightCurtain});
		}
		leftArrow.observe("click", function (event)
		{
			var leftMargin;
			leftMargin = parseInt(this.tabTitle.getStyle("margin-left").gsub("px",""),10)+40;
			if (leftMargin > 0)
			{
				leftMargin = 0;
			}
			this.tabTitle.setStyle({marginLeft : leftMargin+"px"});
		}.bind(this));
		rightArrow.observe("click", function (event)
		{
			var leftMargin;
			leftMargin = (parseInt(this.tabTitle.getStyle("margin-left").gsub("px",""),10)-40);
			if (leftMargin >= -1*(this.getTotalTitleWidth()-this.getTitleWidth()+300))
			{
				this.tabTitle.setStyle({marginLeft : leftMargin+"px"});
			}

		}.bind(this));
		listArrow.observe("click", function (event)
		{
			this.hideAkylaTabList = true;
			setTimeout(function ()
			{
				if (this.hideAkylaTabList)
				{
					list.hide();
				}
			}.bind(this), 2000);
			var akylaTabSummary = $("akylaTabTabSummary");
			if (akylaTabSummary != null)
			{
				akylaTabSummary.remove();
			}
			var pos = listArrow.cumulativeOffset();
			var div = new Element("div", {id : "akylaTabTabSummary"}).addClassName("tabList");
			var list = this.tabTitle.cloneNode(true);
			div.insert({bottom : list});
			list.observe("click",function (event)
			{
				var eventTarget = event.target;
				if (eventTarget.tagName.toLowerCase() != "li")
				{
					eventTarget = eventTarget.up("li");
				}
				this.setActiveTab(eventTarget.readAttribute("objectid"));
				Event.stop(event);
			}.bind(this));
			list.writeAttribute("style",null);
			div.setStyle({left : (pos[0]-300)+"px", top : (pos[1])+"px"});
			$(document.body).insert({bottom : div});
			list.observe("mouseover", function (event)
			{
				this.hideAkylaTabList = false;
				div.observe("mouseout", function (event)
				{
					if (event.target == div)
					{
						this.hideAkylaTabList = true;
						setTimeout(function () 
						{
							if (this.hideAkylaTabList)
							{
								list.hide();
							}
						}.bind(this),250);
					}
				}.bind(this));
			}.bind(this));
		}.bind(this));
	},
	getTitleWidth : function()
	{
		return $$(this.titleSelectors.get("main")).first().up("div").getWidth();
	},
	/**
	 * Shows the title which are refering to the tabs with objectID objectId if these were hidden
	 *
	 * @param integer objectId ObjectId
	 * @param @optional boolean setActive Set the shown tab to active as well?
	 */
	showTab : function(objectId, setActive)
	{
		if (typeof setActive == "undefined")
		{
			setActive = true;
		}
		this.titleSelectors.each(function (pair)
		{
			var title = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (!title.visible())
			{
				title.show();
			}
		});
		if (setActive)
		{
			this.setActiveTab(objectId);
		}
	},
	/**
	 * Returns the contents of the tab identified by objectId and contentSelector.
	 *
	 * @param integer objectId ObjectId
	 * @param @optional string contentSelector The key of the contentSelector of which to yank a content from
	 */
	getTab : function(objectId, contentSelector)
	{
		if (typeof contentSelector == "undefined")
		{
			contentSelector = "main";
		}
		return $$(this.contentSelectors.get(contentSelector)+"[objectid=\""+objectId+"\"]").first();
	},
	/**
	 * Hides the title whish is refering to the object id. If this tab was active,
	 * sets the tab "0" to be the active one.
	 *
	 * @param integer objectId ObjectId
	 */
	hideTab : function(objectId)
	{
		// Algorithm
		// go through all titles, if the objectId was hidden, show it

		if (objectId == 0) // Can't hide the first Tab
		{
			return;
		}
		this.titleSelectors.each(function (pair)
		{
			var title = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (title != null)
			{
				title.hide();
				if (title.hasClassName("active"))
				{
					this.setActiveTab(0);
				}
			}
		}.bind(this));
	},
	/**
	 * Sets a new active tab refered by the objectId.
	 *
	 * @param integer objectId ObjectId
	 */
	setActiveTab: function(objectId)
	{
		/* Algorithm:
		 * 1 - Set old active tabtitles on not active
		 * 2 - Set new active tabtitles active
		 * 3 - Hide old show contents
		 * 4 - Show new contents
		 * 5 - set new active Tab
		 */
		var refreshTab = false;

		// Call the before Change
		this.selfBeforeChange(this.activeTab);

		this.titleSelectors.each(function (pair)
		{
			//1
			var activeTitle = $$(pair.value+"[objectid=\""+this.activeTab+"\"]").first();
			if (activeTitle != null)
			{
				activeTitle.removeClassName("active");
			}
			//2
			var newTitle = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (newTitle != null)
			{
				newTitle.addClassName("active");
					
				refreshTab = refreshTab || newTitle.hasAttribute("href");
				if (pair.key == "main")
				{
					var leftMargin = 0;
					var rightBorder = 0;
					var leftBorder = 0;

					leftMargin = parseInt(this.tabTitle.getStyle("margin-left").gsub("px",""),10);
					rightBorder = newTitle.getWidth()+newTitle.positionedOffset().left;
					leftBorder = newTitle.positionedOffset().left;
					if ( rightBorder  > this.getTitleWidth())
					{
						leftMargin = leftMargin+(this.getTitleWidth()-rightBorder)-30;
						this.tabTitle.setStyle({marginLeft : leftMargin+"px"});
					}
					else if (leftBorder < 0)
					{
						leftMargin = leftMargin-leftBorder+28;
						this.tabTitle.setStyle({marginLeft : leftMargin+"px"});
					}
				}
			}
		}.bind(this));
		this.contentSelectors.each(function (pair)
		{
			//3
			var activeContent = $$(pair.value+"[objectid=\""+this.activeTab+"\"]").first();
			if (activeContent != null)
			{
				if (this.preferences.previewPaned && activeContent.readAttribute("objectid") == "0")
				{
					
				}
				else
				{
					activeContent.hide();
				}
			}
			//4
			var newContent = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (newContent)
			{
				newContent.show();
				if (Akyla.SideBar)
				{
					Akyla.SideBar.repositionSideBar();
				}

				if (pair.key == "main")
				{
					newContent.fire("container:focus");
				}
			}
		}.bind(this));
		// 5
	
		// Call the after change
		if (this.activeTab != objectId)
		{
			this.selfAfterChange(this.activeTab, objectId);
		}
		this.activeTab = objectId;
	},
	/**
	 *
	 * TODO:
	 */
	showContent : function(objectId)
	{
	},
	/**
	 * Adds a new tabtitle to a selecter refering to object with id object id. Will update the title
	 * if it was already exisiting for that given object id in that given selector.
	 *
	 * @param integer objectId Object id
	 * @param string selector Unique name of the title selector. (Remember "main" is the default selector)
	 * @param string title Title of the new tab
	 * @param object preferences Preferences for the new tab title
	 * TODO : preferences
	 */
	addTitle : function(objectId, selector, title, preferences)
	{
		preferences = Object.extend({
			closable : true
		}, preferences);
		var existingTitle = $$(this.titleSelectors.get(selector)+"[objectid=\""+objectId+"\"]").first();
		if (existingTitle != null)
		{
			existingTitle.down("span").update(title);
			existingTitle.fire("container:change");
		}
		else
		{
			var activeTitle = $$(this.titleSelectors.get(selector)+"[objectid=\""+this.activeTab+"\"]").first();
			var tabTitle = this.createTabTitle(objectId,title);
			if (activeTitle != null)
			{
				activeTitle.insert({after : tabTitle});
				activeTitle.up().fire("container:change");
			}
			else
			{
				$$(this.titleSelectors.get(selector)).first().up().insert({bottom : tabTitle});
			}
			if (selector == "main")
			{
				this.tabCount++;
			}
			existingTitle = $$(this.titleSelectors.get(selector)+"[objectid=\""+objectId+"\"]").first();
		}
		// Tab 0 is holy!
		if (preferences.closable && objectId != 0)
		{
			existingTitle.down("span").insert({bottom : this.createCloseButton()});
		}
		var sum = 0;
		$$(this.titleSelectors.get(selector)).each (function (element)
		{
			sum += element.getWidth();
		});
	},
	/**
	 * Adds a new tabcontent to a selecter refering to object with id object id. Will update the content
	 * if it was already existing for that given object id
	 *
	 * @param integer objectId Object id
	 * @param string selector Unique name of the content selector. (Remember "main" is the default selector)
	 * @param string content The actual content
	 * @param object preferences Preferences for the new tab content
	 * TODO : preferences
	 */
	addContent : function(objectId, selector, content, preferences, overlayEnabled)
	{
		preferences = Object.extend({
		}, preferences);
		var parent = $$(this.contentSelectors.get(selector)).first().up();
		var existingContent = $$(this.contentSelectors.get(selector)+"[objectid=\""+objectId+"\"]").first();
		if (existingContent && existingContent.up() == parent)
		{
			existingContent.update(content);
			existingContent.fire("container:change");
			if (overlayEnabled)
				Akyla.Overlay.makeOverlaid(existingContent,"Test edit","Test");
		}
		else
		{
			var newTabContent = this.createTabContent(objectId,content);
			parent.insert({bottom : newTabContent});
			newTabContent.fire("container:change");
			if (overlayEnabled)
				Akyla.Overlay.makeOverlaid(newTabContent,"Test new","Test");
		}
	},
	/**
	 * Adds multiple tab contents and multiple titles for one given object ID
	 *
	 * @param object tabData Tabdata in the form of {titles : {selector : title1, selector1 : title1}, contents : {selector : content1, selector1 : content1}}
	 * @param integer objectId Object id
	 * @param object preferences Preferences for the new tab content
	 * TODO : preferences
	 */
	add: function(objectId, tabData, preferences)
	{
		preferences = Object.extend({
			closable : true
		}, preferences);
		var existingTitle = $$(this.titleSelectors.get("main")+"[objectid=\""+objectId+"\"]").first();
		$H(tabData.titles).each(function (titlePair)
		{
			// Todo : check if the objectId already exists
			this.addTitle(objectId,titlePair.key,titlePair.value,preferences);
		}.bind(this));
		$H(tabData.contents).each(function (contentPair)
		{
			// Todo : check if the objectId already exists
			this.addContent(objectId, contentPair.key, contentPair.value, preferences,tabData.overlayEnabled);
		}.bind(this));
		if (this.preferences.alwaysActivateNewTabs || objectId != 0 && !existingTitle)
		//if (objectId != 0)
		{
			this.setActiveTab(objectId);
		}
		this.selfAfterAdd(objectId);
	},
	/**
	 * Will remove all titles and all contents refering to an object with id objectId. If you
	 * happen to be deleting a tab which is active the new active tab will be set to 0 (the allmighty
	 * non deletable forever existing tab)
	 *
	 * @param integer objectId
	 * @param integet cascade Close the parents as well?
	 */
	remove: function(objectId, cascade)
	{
		var removed = false;
		if (objectId == 0) // Can't remove the first Tab
		{
			return;
		}
		this.titleSelectors.each(function (pair)
		{
			var title = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (title)
			{
				if (title.hasClassName("active"))
				{
					this.setActiveTab(0);
				}
				if (pair.key == "main")
				{
					this.tabCount--;
				}
				this.selfBeforeRemove(objectId, cascade);
				if (title && title.parentNode)
				{
					title.remove();
				}
				this.selfAfterRemove(objectId);
				removed = true;
			}
		}.bind(this));
		this.contentSelectors.each(function (pair)
		{
			var content = $$(pair.value+"[objectid=\""+objectId+"\"]").first();
			if (content && content.parentNode)
			{
				content.remove();
				removed = true;
			}
		}.bind(this));
		if (removed && Akyla.SideBar)
		{
			Akyla.SideBar.repositionSideBar();
		}
	},	/**
	 * This is how a tabtitle is supposed to look like. Internally used for adding tab titles
	 *
	 * @param integer objectId Object id
	 * @param string title Textual title of the tab
	 */
	createTabTitle : function (objectId, title)
	{
		return new Element("li", {"objectid" : objectId}).update(
			new Element("a", {href : "#"}).update(
				new Element("span").update(title)
				)
			).addClassName("title");
	},
	/**
	 * This is how a tabcontent is supposed to look like. Internally used for adding tab contents
	 *
	 * @param integer objectId Object id
	 * @param mixed content Actual content of the tab. Can also be an html element
	 */
	createTabContent : function (objectId, content)
	{
		return new Element("div", { objectid : objectId}).update(content).addClassName("content");
	},
	/**
	 * This is how a close buttons is supposed to look like. Internally used for adding titles
	 */
	createCloseButton : function ()
	{
		var img = new Element("img", {src : Akyla.preferences.baseUrl+"/image/gfx/tabs/close.gif"}).addClassName("closeButton");
		return img;
	},

	/**
	 * Will set the active tab to the first one. (Keep in mind this is always the holy, almight, always present
	 * tab 0)
	 */
	first: function()
	{
		this.setActiveTab(0);
	},
	/**
	 * Will set the active tab to the first "valid" tab after the given one. If none was given the current active tab will be used
	 * for determining the next valid one.
	 *
	 * @param string objectId Id of the tab from which the next active tab will be used. This parameter is also used for internal
	 * recursive calls for whenever the next tab after the current given one is not a valid one.
	 */
	next: function(objectId)
	{
		if (typeof objectId == "undefined")
		{
			objectId = this.activeTab;
		}
		// Check only the main
		var nextTitle = $$(this.titleSelectors.get("main")+"[objectid=\""+objectId+"\"]").first().next();
		if (nextTitle != null )
		{
			if (nextTitle.visible())
			{
				this.setActiveTab(nextTitle.readAttribute("objectid"));
			}
			else
			{
				this.next(nextTitle.readAttribute("objectId"));
			}
		}
	},
	/**
	 * Will set the active tab to the first "valid" tab before the given one. If none was given the current active tab will be used
	 * for determining the previous valid one.
	 *
	 * @param string objectId Id of the tab from which the previous active tab will be used. This parameter is also used for internal
	 * recursive calls for whenever the previous tab before the current given one is not a valid one.
	 */
	previous: function(objectId)
	{
		if (typeof objectId == "undefined")
		{
			objectId = this.activeTab;
		}
		// Check only the main
		var previousTitle = $$(this.titleSelectors.get("main")+"[objectid=\""+objectId+"\"]").first().previous();
		if (previousTitle != null)
		{
			if (previousTitle.visible())
			{
				this.setActiveTab(previousTitle.readAttribute("objectid"));
			}
			else
			{
				this.previous(previousTitle.readAttribute("objectId"));
			}
		}
	},
	/**
	 * Sets the active tab to be the last valid tab possible. If the last one was not valid
	 * this function will internall use previous method to determind the one before that.
	 */
	last: function()
	{
		// Check only the main
		var lastTitle = $$(this.titleSelectors.get("main")).last();
		if (lastTitle != null)
		{
			if (lastTitle.visible())
			{
				this.setActiveTab(lastTitle.readAttribute("objectid"));
			}
			else
			{
				this.previous(lastTitle.readAttribute("objectId"));
			}
		}
	},
	//for extending.
	selfAfterChange: function(oldTabNumber, newTabNumber)
	{
		var newTitle = $$(this.titleSelectors.get("main")+"[objectid="+newTabNumber+"]").first();
		if (newTitle)
		{
			var refreshTab = newTitle.hasAttribute("href");
			if (refreshTab)
			{
				var objectid = newTitle.up("div.content").readAttribute("objectid");
				Akyla.Ajax.ajaxRequest(newTitle.readAttribute("href")+"/objectid/"+objectid+"/tabid/"+newTitle.readAttribute("objectid"),null,{});
			}
		}
		this.afterChange(oldTabNumber, newTabNumber);
	},
	selfBeforeChange: function(oldTabNumber)
	{
		this.beforeChange(oldTabNumber);
	},
	selfBeforeRemove: function(removedTabNumber, cascade) 
	{
		this.beforeRemove(removedTabNumber, cascade);
	},
	selfAfterRemove: function(removedTabNumber) 
	{
		this.afterRemove(removedTabNumber);
	},
	selfAfterAdd : function(addedTabNumber) 
	{
		this.afterAdd(addedTabNumber);
	},
	afterChange: function(oldTabNumber, newTabNumber)
	{
	},
	beforeChange: function(oldTabNumber){},
	afterRemove: function(removedTabNumber) {},
	beforeRemove: function(removedTabNumber) {},
	afterAdd : function(addedTabNumber) {}	
});

/* Example JSON response which can be handled by the Tabs.Widget

var test = {
	"state":"success",
	"messages":[
		{"message":"initialized","type":"error"},
		{"message":"initialized","type":"error"},
		{"message":"test","type":"error"},
		{"message":"info","type":"info"}
	],
	"headerRequirements":[
		{"tag":"script","attributes":{"src":"\/~oz\/naris3\/js\/akyla\/prototype\/JSON\/Tabs.js","type":"text\/javascript"}}
	],
	"callRequirements":[],
	"components":[
		{
			"processingFunction":"Akyla.Widget.Tabs",
			"containerId":"rootTab",
			"objectId":118,
			"operation":"default",
			"titles":
			{
				"main":"Hello"
			},
			"contents":
			{
				"main":"<form action=\"\/~oz\/naris3\" method=\"post\" id=\"resourceInsertForm\" enctype=\"application\/x-www-form-urlencoded\" class=\" jsValidate\"><fieldset><legend>Resource<\/legend><input type=\"hidden\" name=\"acl_resource_id\" id=\"resourceInsertForm_acl_resource_id\" \/><div class=\"formPair\"><label for=\"resourceInsertForm_acl_resource_name\">Resource name<\/label><input type=\"text\" name=\"acl_resource_name\" id=\"resourceInsertForm_acl_resource_name\" title=\"The name of the resource\" class=\" toolTipped\" \/><\/div><div class=\"formPair\"><label for=\"resourceInsertForm_acl_resource_parent_id\">Resource parent<\/label><select name=\"acl_resource_parent_id\" id=\"resourceInsertForm_acl_resource_parent_id\"><option value=\"\" label=\"Select a parent\" selected=\"selected\">Select a parent<\/option><option value=\"19\" label=\"&nbsp;&nbsp;asfsad\">&nbsp;&nbsp;asfsad<\/option><option value=\"2\" label=\"&nbsp;&nbsp;Test\">&nbsp;&nbsp;Test<\/option><option value=\"27\" label=\"&nbsp;&nbsp;&nbsp;&nbsp;asfdfsd\">&nbsp;&nbsp;&nbsp;&nbsp;asfdfsd<\/option><option value=\"28\" label=\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;asfdasdf\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;asfdasdf<\/option><option value=\"3\" label=\"&nbsp;&nbsp;&nbsp;&nbsp;asdfasd\">&nbsp;&nbsp;&nbsp;&nbsp;asdfasd<\/option><option value=\"30\" label=\"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;asdfsdf\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;asdfsdf<\/option><\/select><\/div><\/fieldset><input type=\"submit\" value=\"Insert\" \/><input type=\"reset\" \/><\/form>","sideBar":"Test extra content :118"
			}
		}
	]
}		

*/

