/**
* TabControl creates tabs for defined contents.
*
* @uses MooTools v1.2
* @version 1.1
* @license MIT-style license
* @author Jean-Bernard Valentaten - <troggy [dot] brains [at] gmx [dot] de>
* @copyright Author
*/
//create class
TabControl = new Class();
/**
* Options:
*
* Name			| Type		| Description
* ------------------------------------------------------------------------------------------------
* behaviour		| String	| Defines whether the panes shall be shown on 'click' (default) or 'mouseover'
* hoverClass	| String	| The css-class that will be assigned to a tab when being hovered, if behaviour is set to 'click' (defaults to empty string)
* initialTab	| String	| The id of the tab that will be selected on initialization (defaults to first tab)
* onChange		| Callback	| Fired whenever the tab is changed. Passes the currently visible pane and selected tab
* panes			| Array		| The (ids of the) panes in the correct order. If missing will use css-rule div#pane<N> within element
* selectedClass	| String	| The css-class that will be assigned to the selected tab (defaults to empty string)
* tabs			| Array		| The (ids of the) tabs in the correct order. If missing will use css-rule div#tab<N> within element
*/
TabControl.prototype = {
	/**
	 * Constructor
	 *
	 * @param {Element,String} element The element that will be used as container for the tab-control
	 * @param {Object} [options] The options as seen above
	 */
	initialize: function(element, options) {
		//init vars
		var tabcontrol = this;
		
		//init datamembers
		this.element = $(element);
		this.options = $extend({
			behaviour: 'click',
			hoverClass: '',
			initialTab: '',
			onChange: $empty,
			selectedClass: ''
		}, options);
		this.panes = new Array();
		this.tabs = new Array();
		
		//grab optional datamembers
		this.behaviour = this.options.behaviour;
		this.hoverClass = this.options.hoverClass;
		this.initialTab = this.options.initialTab;
		this.onChange = this.options.onChange;
		this.selectedClass = this.options.selectedClass;
		
		//init tabs and panes
		this._initTabs();
		this._initPanes();
		
		//redefault initial tab if needed and have it displayed
		if (!this.initialTab) {
			this.initialTab = this.tabs[0];
		}
		this.selectTab(null, this.initialTab);
	},
	
	/**
	 * Destructor
	 */
	dispose: function() {},
	
	/*
	 * Private methods
	 */
	
	/**
	 * Grabs the panes
	 * 
	 * @private
	 */
	_initPanes: function() {
		//init vars
		var panes = this.options.panes || new Array();
		
		//if we don't have panes, we try to grab 'em
		if (!panes.length) {
			this.element.getElements('div').each(function(el) {
				if (el.id && el.id.search(/^pane(\d+)$/)==0) {
					panes.push(el);
				}
			});
		}
		
		//iterate through panes adding them to our 
		//panes-datamember
		panes.each(function(s) {
			this.panes.push($(s));
		}, this);
	},
	
	/**
	 * Grabs the tabs and installs listeners
	 * 
	 * @private
	 */
	_initTabs: function() {
		//init vars
		var tabs = this.options.tabs || new Array();
		
		//if we don't have tabs, we try to grab 'em
		if (!tabs.length) {
			this.element.getElements('div').each(function(el) {
				if (el.id && el.id.search(/^tab(\d+)$/)==0) {
					tabs.push(el);
				}
			});
		}
		
		//iterate through tabs adding them to our 
		//tabs-datamember and setting up listeners
		tabs.each(function(s) {
			var elem = $(s);
			
			//add an eventlistener
			elem.addEvent(this.behaviour, this.selectTab.bindWithEvent(this, elem));
			
			//if we're not in 'mouseover'-mode and hoverClass is set, we add a listener for hovering
			if (this.behaviour!='mouseover') {
				elem.addEvent('mouseover', this.highlightTab.bind(this, elem));
				elem.addEvent('mouseout', this.unHighlightTab.bind(this, elem));
			}
			this.tabs.push(elem);
		}, this);
	},
	
	/*
	 * Public methods
	 */
	
	/**
	 * Returns the index of the specified tab
	 * 
	 * @param {String,Element} tab The tab whose index shall be returned
	 * @return {int} The index of the specified tab if tab is valid, -1 otherwise
	 */
	getTabIndex: function(tab) {
		//return the index of specified tab
		return this.tabs.indexOf($(tab));
	},
	
	/**
	 * Hightlights currently hovered tab by adding hoverClass to it
	 * and removes hoverClass from all others.
	 * 
	 * @param {String,Element} tab The tab where mousecursor is curretly over 
	 */
	highlightTab: function(tab) {
		//if no hoverClass is defined, we terminate
		if (!this.hoverClass) return;
		
		//if tab does not have hoverClass, we add it
		if (!tab.hasClass(this.hoverClass)) tab.addClass(this.hoverClass);
	},
	
	/**
	 * Will select specified tab and show its associated pane.
	 *
	 * @param {Event} evt The event that fired this function (can be null if used from external script)
	 * @param {Element} tab The tab for which a pane shall be shown
	 */
	selectTab: function(evt, tab) {
		//init vars
		var currentPane;
		var currentTab;
		
		//make sure tab is extended
		tab = $(tab);
		
		//iterate through tabs, showing/hiding the associated panes
		this.tabs.each(function(s, n) {
			if (s===tab) {
				s.addClass(this.selectedClass);
				if (this.panes[n]) this.panes[n].setStyle('display', 'block');
				currentPane = this.panes[n];
				currentTab	= s;
			} else {
				s.removeClass(this.selectedClass);
				if (this.panes[n]) this.panes[n].setStyle('display', 'none');
			}
		}, this);
		
		//finally, we call the onChange-callback
		this.onChange(currentPane, currentTab);
	},
	
	/**
	 * Selects a tab by its index and shows its associated pane.
	 * If index is not valid and force is not set, terminates 
	 * without any change. If index is not valid and force is 
	 * set, displays either first or last tab, depending on which 
	 * bound is nearer to index (e.g. with index set to -1, first
	 * tab ist selected)
	 * 
	 * @param {int} index The index of the tab that shall be selected
	 * @param {bool} [force] Force a tab to be selected even if index is not valid (defaults to false) 
	 */
	selectTabByIndex: function(index, force) {
		//do we have to force an action
		if (index<0 && force) {
			index = 0
		} else if (this.tabs.length<=index && force) {
			index = this.tabs.length-1;
		} else if (index<0 || index>=this.tabs.length) {
			return;
		}
		
		//select that tab and off we go
		this.selectTab(null, this.tabs[index]);
	},
	
	unHighlightTab: function(tab) {
		//if no hoverClass is defined, we terminate
		if (!this.hoverClass) return;
		
		//if tab does have hoverClass, we remove it
		if (tab.hasClass(this.hoverClass)) tab.removeClass(this.hoverClass);
	}
};
