/**
 * @fileOverview This file contains all necessary classes for drop-down tab functionality.
 * @author Popular Front
 */

/**
 * @lends DropDownMenu.prototype
 */
var Tab = Class.create({
	/**
	 * Displays and hides a drop-down tab based on interaction with a trigger element.
	 *
	 * @constructs
	 * @param {Element} trigger DOM element that causes the drop down tab to display on mouseover.
	 * @param {Element} tab DOM element that gets displayed and hidden.
	 * @param {Object} [options] Container for customizable features.
	 * @param {String} [options.triggerClass] CSS class that is applied to trigger while tab is open.
	 */
	initialize: function(trigger, tab, options) {
		// set defaults
		if(!options) options = {};
		if(!options.animate) options.animate = false;
		if(!options.animationOpen) if(Effect) options.animationOpen = Effect.Appear;
		if(!options.animationOpenOptions) options.animationOpenOptions = {duration: .3, queue: 'end'};
		if(!options.animationClose) if(Effect) options.animationClose = Effect.Fade;
		if(!options.animationCloseOptions) options.animationCloseOptions = {duration: .3, queue: 'front'};
		
		this.options = options;
		this.delegate = null;
		this.trigger = $(trigger);
		this.tab = $(tab);
		
		this.tabStyles = this.tab.style;
		
		// event listener handlers
		this.onTriggerClick = this.onTriggerClick.bindAsEventListener(this);
		this.close = this.close.bind(this);
		this.onAnimationOpenFinish = this.onAnimationOpenFinish.bind(this);
		this.onAnimationCloseFinish = this.onAnimationCloseFinish.bind(this);
		
		// event listeners
		trigger.observe('click', this.onTriggerClick);
	},
	

	/**
	 * Displays tab when mouse is placed over trigger element. If a triggerClass is specified, 
	 * a CSS class will be used while the tab is open.
	 *
	 * @private
	 */
	onTriggerClick: function(event){
		this.options.autoRotate = false;
		this.delegate.onTabClick(this);
		
		this.open();
	},
	

	
	/**
	 * Display the tab.
	 */
	open: function(){
	
			
		if (this.options.triggerClass) 
			this.trigger.addClassName(this.options.triggerClass);
		
		if(this.delegate) 
			this.delegate.onTabOpen(this);
		
		if(this.tab.visible())
				return;
			
		if(this.options.animate) {
			if(this.options.animationOpen) {
				if(!this.animationClose && !this.animationOpen) {
					this.options.animationOpenOptions.afterFinish = this.onAnimationOpenFinish;
					this.animationOpen = new this.options.animationOpen(this.tab, this.options.animationOpenOptions);
					return;
				}
			}
		}
		else
				this.tab.show();
		
		
	},
	
	/**
	 * Hide the tab from display.
	 */
	close: function(){
				
		if (this.options.triggerClass)
			this.trigger.removeClassName(this.options.triggerClass);
		
		if(!this.tab.visible())
			return;
			
		
		if(this.options.animate) {
			if(this.options.animationClose) {
				/*if(this.animationOpen) {
					this.onAnimationOpen.cancel();
				}*/
				
				if(!this.animationClose) {
					this.options.animationCloseOptions.afterFinish = this.onAnimationCloseFinish;
					this.animationClose = new this.options.animationClose(this.tab, this.options.animationCloseOptions);
					return;
				}
			}
		}
		else
				this.tab.hide();
		
	},


	
	onAnimationOpenFinish: function() {
		this.animationOpen = null;
	},
	
	onAnimationCloseFinish: function() {
		this.animationClose = null;
	}
	
	
});

/**
 * @lends DropDownMenuGroup.prototype
 */
var TabGroup = Class.create({
	/**
	 * Links multiple tabs together to improve user experience.
	 *
	 * @constructs
	 *
	 * @param {DropDownMenu[]} tabs Array of DropDownMenu objects.
	 * @param {Object} [options] Container for customizable features.
	 * @param {String} [options.triggerClass] CSS class that is applied to trigger while tab is open. Setting applies to all triggers unless otherwise specified.
	 */
	initialize: function(tabs, options) {
	
		// set defaults
		if(!options) options = {};
		this.tabs = tabs;
		if(!options.autoRotate) options.autoRotate = false;
		if(!options.autoRotateDuration) options.autoRotateDuration = 5;
		
		this.options = options;
		
		
		this.playRotation = this.playRotation.bind(this);


		var length = tabs.length;
		
		// loop over tabs to apply settings
		for(var i=0; i<length; ++i){
			var tab = tabs[i];
			// define each tab's delegate as the group's object
			tab.delegate = this;
			// apply group properties to each tab if tabs are left unspecified
			for(var key in options){
				if(!tab.options[key]) 
					tab.options[key] = options[key];
			}

		}
		
		if(options.autoRotate){
			this.playRotation(0);
		} else {
			this.tabs[0].open();
		}
		
		
	},
	
	playRotation: function(thisTab){
		this.tabs[thisTab].open();
		clearTimeout(this.timy);	
		nextTab = thisTab + 1;
		if (nextTab > (this.tabs.length - 1)){
			nextTab = 0;
		}
		if(this.options.autoRotate)
			this.timy = setTimeout(function() { this.playRotation(nextTab); }.bind(this), this.options.autoRotateDuration);
	},
	
	/**
	 * @private
	 */
	onTabOpen: function(tab) {
		var length = this.tabs.length;
		for(var i=0; i<length; ++i){
			var m = this.tabs[i];
			if (m != tab)
				m.close();
		}
	},
	
	onTabClick: function(tab){
		clearTimeout(this.timy);
	}
	
	
	
	
});


