/**
* @fileoverview This file contains the tab object
* @author Andrew Tourtellot
* @version 0.1
*/

/**
* This is a tab object that handles tab functionalities.
* @object
*/
var Tab = Class.create();
Tab.prototype = {
	/**
	* declares all variables needed for a tab. everything related to the actual HTML elements a tab is comprised of is actually instantiated in a different function, makeNewDivs 
	* @param {String} tabID
	* @param {String} tabName
	* @param {Object} system
	*/
	initialize: function(tabID,tabName,system,perm) {
		this.id = tabID; // unique string id for tab
		this.name = tabName; // string name to be displayed for tab
		this.tabElem = null; // tab content element for this tab
		this.labelElem = null; // label element for this tab
		this.label = null;
		this.mySystem = system;
		this.frontMe = this._frontMe.bindAsEventListener(this);
		this.closed = false;
		this.permanent = perm;
		
		// Functions to run on close, hide, and show
		this.showFunc = null;
		this.hideFunc = null;
		this.closeFunc = null;
	},
	
	/** calls changeTab on itself to bring itself to the front 
	* @event
	*/
	_frontMe: function(event) {
		this.mySystem.changeTab(this,false);
	},
		
	/** makes new html elements for the tab label and the tab content area, and inserts them in the page. also sets up appropriate observers
	*/
	makeNewDivs: function(tabID, labs,conts) {
		tabID = tabID + '-tab';
		this.tabElem = $E({
			id: tabID,
			tag: 'div',
			className: 'tabContents',
			children: ''
		});

		this.labelElem = $E({
			tag: 'div',
			className: 'tabLabel',
			children: 
			{	tag: 'a',
				href: '#',
				className: 'tabLink',
				children: 
				{	
					tag: 'span',
					children: this.name
				}
			}
		});

		
		this.tabElem.style.display='none';

		labs.appendChild(this.labelElem);
		conts.appendChild(this.tabElem);

		Event.observe(this.labelElem, "click", this.frontMe);

	},
	
	/** removes html elements for the tab label and the tab content area from the page */
	removeDivs: function() {
		this.labelElem.stopObserving("click",this.frontMe);

		this.labelElem.remove();
		this.tabElem.remove();
	},
	
	/**
	* called by the system, handles all color changes for tabs and labels, and makes the tab itself visible
	* @param {Object} labs label to be shown
	*/
	show: function(labs) {
		this.tabElem.style.display='';
		
		if (!$('tabBody').visible())
			Effect.BlindDown($('tabBody'), {duration:0.5});
			
		if (this.showFunc != null) {
			this.showFunc();
		}
		
		if (this.closed) {
			this.reOpen(labs);
		}

		this.labelElem.addClassName('activeTabLabel');
	},
	
	/** 
	* called by the system, handles all color changes for tabs and labels, and makes the tab itself hide
	*/
	hide: function() {
		this.tabElem.style.display='none';
		
		if (this.hideFunc != null) {
			this.hideFunc();
		}

		this.labelElem.removeClassName('activeTabLabel');
	},
	
	/** called by the system, handles all hiding of tab and labels when a tab is closed (but retained) or removal of all elements when it is closed (and not retained)
		returns true if it is retained, or false if not */
	close: function() {
		// protect from accidental re-closings
		if (this.closeFunc != null) {
			this.closeFunc();
		}
		
		if (this.closed) {
			return true;
		}
		this.labelElem.remove();
		if (this.permanent) {
			this.closed = true;
			this.tabElem.style.display = 'none';
			
			if (this.labelElem.hasClassName('activeTabLabel')) {
				this.labelElem.removeClassName('activeTabLabel');
			}
			return true;
		}
		this.labelElem.stopObserving("click",this.frontMe);
		this.tabElem.remove();
		return false;
	},
	
	/** called by the system, handles re-adding of label when a closed-but-retained tab is re-opened 
	* @param {object} labs the label elements
	*/
	reOpen: function(labs) {
		this.closed = false;
		labs.appendChild(this.labelElem);
	},
	
	/** called by the system, hides or shows tab to effect a toggle of its visibility 
	* @param {object} labs the label elements
	*/
	toggle: function(labs) {
		if (this.tabElem.style.display=='') {
			this.hide();
		}
		else {
			this.show(labs);
		}
	},
	
	/** replaces current tab content with the results of a php request, and switches system to this tab, IF the request is a success
	* @param {String} request the url request string
	*/
	loadContent: function(request) {
		var tab = this;
		new Ajax.Updater(this.tabElem,request, {
			onSuccess: function(response) {
				tab.mySystem.changeTab(tab,false);
			}
		});
	},
	
	/* THE FOLLOWING TABS ARE YOUR PRIMARY WAY TO INSERT CONTENT IN A TAB. THE $E FUNCTION IN FUNCTIONS.JS IS VERY HELPFUL
		FOR CREATING ELEMENTS YOU WANT AS WELL.
		Each of these functions clears and inserts, or just inserts, something into the tab's contents. They also make the system change to show this tab.
		If the content was dependent on a PHP request, the tab switch only happens when the request returs. */
	
	/** replaces current tab content with the results of a php request, and switches system to this tab, IF the request is a success. enables scripts on the response.
		may be combined with loadContent soon. 
	* @param {String} request the url request string
	*/
	loadContentWithScripts: function(request) {
		var tab = this;
		new Ajax.Updater(this.tabElem,request, {
			onSuccess: function(response) {
				tab.mySystem.changeTab(tab,false);
			},
			evalScripts: true
		});
	},
	
	/** appends results of a php request to the tab's contents without replacing old contents, by wrapping it in a div, which is returned to the caller.
		may be combined with loadContent soon, utilizing the insertion option of Ajax.Updater 
	* @param {String} request the url request string
	*/
	appendContentInDiv: function(request) {
		var tab = this;
		var div = $E({
			tag: 'div',
			className: 'tabSubContent'
		});
		new Ajax.Updater(div,request, {
			onSuccess: function(response) {
				tab.tabElem.appendChild(div);
				tab.mySystem.changeTab(tab,false);
			}
		});
		return div;
	},
	
	/** clears current tab contents and replaces with an HTML element, just as loadContent does with PHP responses. */
	loadElement: function(element) {
		this.tabElem.update();
		this.tabElem.appendChild(element);
		this.mySystem.changeTab(this,false);
	},
	
	/**  appends an HTML element to the end of a tab's contents, just as appendContentInDiv does for PHP, but without the div. */
	appendElement: function(element) {
		this.tabElem.appendChild(element);
		this.mySystem.changeTab(this,false);
	}
	
}