(function() {

var $ = document.id;

this.MooTabs = new Class({

	Implements: [Events, Options],

	options: {
		classes: {
			selected: "selected"
		}
	},

	/**
	 * initialize the component
	 *
	 * @param Element listItem The ul element that contains the tabs
	 * @param Object options The components configuration options
	 */
	initialize: function(listItem, options)
	{
		this.setOptions(options);
		this.listItem = $(listItem);
		// find the links inside the list
		var links = this.listItem.getElements("li");
		links.each(function(item) {
			var link = item.getFirst("a");
			// make the links clickable
			link.addEvent("click", this.tabClickEventHandler.bindWithEvent(this));
			// the panel associated with the tab
			var href = link.getProperty("href");
			var id = href.substr(href.indexOf("#") + 1);
			var div = $(id);
			// no error checking, errors are not allowed
			div.setStyle("display", "none");
		}, this);
		// pre-select the first tab
		this.tabClickEventHandler({target: this.getCurrentTab(), stopPropagation: function() {}, stop: function() {}});
	},

	/**
	 * Gets a handle on the currently selected tab
	 *
	 * @return Element
	 */
	getCurrentTab: function()
	{
		var list = this.listItem.getElements("li a.selected");
		if (list.length > 0)
		{
			currentTab = list[0];
		}
		else
		{
			// get the first tab
			currentTab = this.listItem.getFirst("li").getFirst("a");
		}
		return currentTab;
	},

	/**
	 * De-selects the current tab
	 */
	clearCurrentSelection: function()
	{
		this.getCurrentTab().removeClass(this.options.classes.selected);
	},

	/**
	 * Handles tab click events
	 *
	 * @param Event e The event
	 */
	tabClickEventHandler: function(e)
	{
		e.stopPropagation();
		e.stop();
		var tab = $(e.target);
		if (tab.nodeName.toUpperCase() == "SPAN")
		{
			tab = tab.getParent("a");
		}
		this.selectTab(tab);
	},

	/**
	 * Selects the next tab
	 *
	 * @return Element/bool The next tab (now the current tab) or false if not possible
	 */
	moveNext: function()
	{
		var nextTab;
		if (nextTab = this.getNextTab(this.getCurrentTab()))
		{
			this.selectTab(nextTab);
		}
		return nextTab;
	},

	/**
	 * Selects the previous tab
	 *
	 * @return Element/bool The previous tab (now the current tab) or false if not possible
	 */
	movePrevious: function()
	{
		if (prevTab = this.getPreviousTab(this.getCurrentTab()))
		{
			this.selectTab(prevTab);
		}
		return prevTab;
	},

	/**
	 * selects a tab and shows its panel
	 *
	 * @param Element tab a handle on the link element of the tab
	 */
	highlightTab: function(tab)
	{
		this.clearCurrentSelection();
		tab.addClass(this.options.classes.selected);
		var panel = $(this.getTabId(tab.getProperty("href")));
		if (this.currentPanel)
		{
			this.hidePanel(this.currentPanel);
		}
		if (panel)
		{
			this.currentPanel = panel;
			this.showPanel(panel);
		}
	},

	/**
	 * selects a tab and fires the change event
	 *
	 * @param Element tab A handle on the tab to select
	 */
	selectTab: function(tab)
	{
		this.highlightTab(tab);
		this.fireEvent("change", tab);
	},
	
	/**
	 * Hides a panel
	 *
	 * @param Element panel The panel to hide
	 */
	hidePanel: function(panel)
	{
		panel.setStyle("display", "none");
	},

	/**
	 * Shows a panel
	 *
	 * @param Element panel The panel to show
	 */
	showPanel: function(panel)
	{
		panel.setStyle("display", "block");
	},

	/**
	 * retrieves the id of a tab from its href attribute
	 *
	 * @param string href The contents of a href attribute
	 * @return string
	 */
	getTabId: function(href)
	{
		return href.substr(href.indexOf("#") + 1);
	},

	/**
	 * attempt to get the next tab
	 *
	 * @param Element tab The reference tab
	 * @return Element/bool The next tab or false if none exists
	 */
	getNextTab: function(tab)
	{
		var nextTab = false;
		var nextLi;
		if ((nextLi = tab.getParent("li").getNext("li")))
		{
			nextTab = nextLi.getFirst("a");
		}
		return nextTab;
	},

	/**
	 * attempt to get the previous tab
	 *
	 * @param Element tab The reference tab
	 * @return Element/bool the next tab or false if none exists
	 */
	getPreviousTab: function(tab)
	{
		var prevTab = false;
		var prevLi;
		if ((prevLi = tab.getParent("li").getPrevious("li")))
		{
			prevTab = prevLi.getFirst("a");
		}
		return prevTab;
	}

});

})();
