/*====================================*\
|| ################################## ||
|| # iDeal 2.0 Ajax Core            # ||
|| # ------------------------------ # ||
|| # Copyright ©2008 MediaPulse     # ||
|| # ------------------------------ # ||
|| # Revision Alpha                 # ||
|| ################################## ||
\*====================================*/

/**
 * Accordian controller. This class expects the following html structure
 * for the accordian object.  Overall the accordian is a unordered list
 * object <ul>. The panels are the list items, and these lists need to
 * contain a header tag <h1> and a <div> as their two child elements. Also
 * remember that the Effect.SlideDown and Effect.Blind classes require you
 * to nest one div inside the div to be animated.
 *
 * The accordian will assign the class Active to the panel that is currently
 * open.  
 */
iDeal.Accordian = Class.create({
	/**
	 * Reference to the accordian list object
	 *
	 * @var element
	 * @access protected
	 */
	_myTarget: null,
	
	/**
	 * Reference to the panel in the active state.
	 * Used only when in showOnlyOne mode.
	 *
	 * @var element
	 * @access protected
	 */
	_active: null,
	
	/**
	 * Working element (used by onClick)
	 */
	_working: null,
	
	/**
	 * Flag to show that we are animating the accordian. We ignore
	 * all events when this is set true.
	 */
	_transitionInProgress: false,
	
	/**
	 * Duration of the appearance effect.
	 *
	 * @var float
	 * @access protected
	 */
	_fadeIn: 1,
	
	/**
	 * Duration of the fade out effect
	 * 
	 * @var float
	 * @access protected
	 */
	_fadeOut: 1,
	
	/**
	 * Setting to show only one section of the accordian
	 * at a time
	 *
	 * @var boolean
	 * @access protected
	 */
	_showOnlyOne: true,
	
	/**
	 * Setting to determine if we close on click.
	 *
	 * @var boolean
	 * @access protected
	 */
	_closeOnClick: true,
	
	/**
	 * Type of effect used to appear the popup
	 * (See Scriptaculous Effect Library - SlideDown and BlindDown
	 *  are recommended)
	 *
	 * @var string
	 * @access protected
	 */
	_enterTween: 'SlideDown',

	/**
	 * Type of effect used to exit the popup
	 * (See Scriptaculous Effect Library - SlideUp and BlindUp
	 *  are recommended)
 	 *
	 * @var string
	 * @access protected
	 */
	_exitTween: 'SlideUp',
	
	/**
	 * Cache for the bound onClick function.
	 *
	 * @var bound function object
	 * @access public
	 */
	onClick: null,
	
	/**
	 * Initialize the popup controller.
	 *
	 * @param hash {
	 *		target - target div of the controller REQUIRED
	 *		fadeIn - time in seconds to fade in
	 *		fadeOut - time in seconds to fade out
	 *	}
	 * @return  void
	 * @access public (constructor)
	 * @throws missingRequiredParam
	 */
	initialize: function ( params ) {
		if (!(this._myTarget = $(params.target)))
		{
			throw missingRequiredParam;
		}
			
		// Attach parameters
		this._fadeIn = (params.fadeIn) ? params.fadeIn : this._fadeIn;
		this._fadeOut = (params.fadeOut) ? params.fadeOut : this._fadeOut;
		this._showOnlyOne = (params.showOnlyOne) ? params.showOnlyOne : this._showOnlyOne;
		this._closeOnClick = (params.closeOnClick) ? params.closeOnClick : this._closeOnClick;
		
		// Create the bound copies of the event functions
		this.onClick = this._onClick.bindAsEventListener(this);
		
		// Register the click event to each of the headers.
		this._myTarget.select('li h1').invoke('observe', 'click', this.onClick);
	
		// Get the element that is active. If multiple elements start as
		// active this only fetches the first.
		this._active = this._myTarget.select('.Active')[0];
		
		if (iDeal.debug)
		{
			iDeal.console.log('Accordian Registered.');
		}		
	},
	
	_onClick: function ( e ) {
		this._working = e.findElement('li');
		
		if(this._closeOnClick)
		{
			if(e.findElement('h1').next('div').visible())
			{
				this._hide();
				if (this._active == this._working)
				{
					this._active = null;
				}
			}
			else if (this._active == null)
			{
				this._appear();	
			}
			else if (this._active != this._working)
			{
				if (this._showOnlyOne)
				{
					this._switch();
				}
				else
				{
					this._appear();
				}
			}
		}
		else if (this._active == null)
		{
			this._appear();	
		}
		else if (this._active != this._working)
		{
			if (this._showOnlyOne)
			{
				this._switch();
			}
			else
			{
				this._appear();
			}
		}
	},
	
	_hide: function(e) {
		if (!this._transitionInProgress)
		{
			this._transitionInProgress = true;
			this._working.removeClassName('Active');			
			new Effect[this._exitTween]( this._working.down('div'), {duration: this._fadeOut, afterFinish: function(){ this._transitionInProgress = false }.bindAsEventListener(this) } );	

		}
	},
	
	_switch: function(e) {
		if (!this._transitionInProgress)
		{
			this._transitionInProgress = true;
			this._working.addClassName('Active');
			this._active.removeClassName('Active');
			new Effect.Parallel(
				[ new Effect[this._exitTween](this._active.down('div')) ,
				  new Effect[this._enterTween]( this._working.down('div') )], {
			duration: this._fadeIn, afterFinish: function(){ this._transitionInProgress = false }.bindAsEventListener(this) } );
			this._active = this._working;
		}
	},
	
	_appear: function() {
		if (!this._transitionInProgress)
		{
			this._transitionInProgress = true;
			this._working.addClassName('Active');
			new Effect[this._enterTween]( this._working.down('div'), {duration: this._fadeIn, afterFinish: function(){ this._transitionInProgress = false }.bindAsEventListener(this) } );		
			
			this._active = this._working;
		}
	}
});
