/**
 * Interface Elements for jQuery
 * Accordion
 * 
 * http://interface.eyecon.ro
 * 
 * Copyright (c) 2006 Stefan Petre
 * Dual licensed under the MIT (MIT-LICENSE.txt) 
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 */

/**
 * Create an accordion from a HTML structure
 *
 * @example $('#myAccordion').Accordion(
 *				{
 *					headerSelector	: 'dt',
 *					panelSelector	: 'dd',
 *					activeClass		: 'myAccordionActive',
 *					hoverClass		: 'myAccordionHover',
 *					panelHeight		: 200,
 *					speed			: 300
 *				}
 *			);
 * @desc Converts definition list with id 'myAccordion' into an accordion width dt tags as headers and dd tags as panels
 * 
 * @name Accordion
 * @description Create an accordion from a HTML structure
 * @param Hash hash A hash of parameters
 * @option Integer panelHeight the pannels' height
 * @option String headerSelector selector for header elements
 * @option String panelSelector selector for panel elements
 * @option String activeClass (optional) CSS Class for active header
 * @option String hoverClass (optional) CSS Class for hovered header
 * @option Function onShow (optional) callback called whenever an pannel gets active
 * @option Function onHide (optional) callback called whenever an pannel gets incative
 * @option Function onClick (optional) callback called just before an panel gets active
 * @option Mixed speed (optional) animation speed, integer for miliseconds, string ['slow' | 'normal' | 'fast']
 * @option Integer crrentPanel (otional) the active panel on initialisation
 *
 * @type jQuery
 * @cat Plugins/Interface
 * @author Stefan Petre
 */
jQuery.iAccordion = {
    build: function(options) {
        return this.each(
			function() {
			    if (!options.headerSelector || !options.panelSelector || !options.proceedButtonSelector || !options.previousButtonSelector)
			        return;
			    var el = this;
			    el.accordionCfg = {
			        panelHeight: options.panelHeight || 300,
			        headerSelector: options.headerSelector,
			        proceedButtonSelector: options.proceedButtonSelector,
			        previousButtonSelector: options.previousButtonSelector,
			        panelSelector: options.panelSelector,
			        activeClass: options.activeClass || 'fakeAccordionClass',
			        hoverClass: options.hoverClass || 'fakeAccordionClass',
			        onShow: options.onShow && typeof options.onShow == 'function' ? options.onShow : false,
			        onHide: options.onShow && typeof options.onHide == 'function' ? options.onHide : false,
			        onClick: options.onClick && typeof options.onClick == 'function' ? options.onClick : false,
			        headers: jQuery(options.headerSelector, this),
			        panels: jQuery(options.panelSelector, this),
			        proceedButtons: jQuery(options.proceedButtonSelector, this),
			        previousButtons: jQuery(options.previousButtonSelector, this),
			        speed: options.speed || 400,
			        currentPanel: options.currentPanel || 0,
			        wraparoundPanelIndex: options.wraparoundPanelIndex
			    };
			    el.accordionCfg.panels
					.hide()
					.css('height', '1px')
					.eq(0)
					.css(
						{
						    height: el.accordionCfg.panelHeight + 'px',
						    display: 'block'
						}
					)
					.end();
			    el.accordionCfg.previousButtons
				    .bind(
					'click',
					function(e) {
					    this.accordionPos = el.accordionCfg.currentPanel - 1;

					    var nextPanel = el.accordionCfg.panels
							.eq(this.accordionPos)
							.css({ height: 0, display: 'block' });
					    el.accordionCfg.headers
							.eq(el.accordionCfg.currentPanel)
							.removeClass(el.accordionCfg.activeClass)
							.end()
							.eq(this.accordionPos)
							.addClass(el.accordionCfg.activeClass);

					    el.accordionCfg.panels
						.eq(el.accordionCfg.currentPanel)
							.animate(
								{ height: 0 },
								{
								    duration: el.accordionCfg.speed,
								    step: function(curr) {
								        nextPanel.css('height', el.accordionCfg.panelHeight - curr + 'px');
								    },
								    complete: function() {
								        this.style.display = 'none';
								        if (el.accordionCfg.onHide) {
								            el.accordionCfg.onHide.apply(el, [this]);
								        }
								    }
								}
							);

					    if (el.accordionCfg.onClick) {
					        el.accordionCfg.onClick.apply(
								el,
								[
									this,
									el.accordionCfg.panels.get(this.accordionPos),
									el.accordionCfg.headers.get(el.accordionCfg.currentPanel),
									el.accordionCfg.panels.get(el.accordionCfg.currentPanel)
								]
							);
					    }
					    el.accordionCfg.currentPanel = this.accordionPos;

					}
				)
				.eq(0)
                .end();

			    el.accordionCfg.proceedButtons
				    .each(
					    function(nr) {
					        this.accordionPos = nr + 1;
					        //wrap around
					        if (el.accordionCfg.panels.length == this.accordionPos) {
					            this.accordionPos = el.accordionCfg.wraparoundPanelIndex;
					        }
					    }
				    )
				    .bind(
					'click',
					function(e) {


					    if (el.accordionCfg.currentPanel == this.accordionPos)
					        return;
					    var nextPanel = el.accordionCfg.panels
							.eq(this.accordionPos)
							.css({ height: 0, display: 'block' });
					    el.accordionCfg.headers
							.eq(el.accordionCfg.currentPanel)
							.removeClass(el.accordionCfg.activeClass)
							.end()
							.eq(this.accordionPos)
							.addClass(el.accordionCfg.activeClass);

					    el.accordionCfg.panels
						.eq(el.accordionCfg.currentPanel)
							.animate(
								{ height: 0 },
								{
								    duration: el.accordionCfg.speed,
								    step: function(curr) {
								        nextPanel.css('height', el.accordionCfg.panelHeight - curr + 'px');
								    },
								    complete: function() {
								        this.style.display = 'none';
								        if (el.accordionCfg.onHide) {
								            el.accordionCfg.onHide.apply(el, [this]);
								        }
								    }
								}
							);

					    if (el.accordionCfg.onClick) {
					        el.accordionCfg.onClick.apply(
								el,
								[
									this,
									el.accordionCfg.panels.get(this.accordionPos),
									el.accordionCfg.headers.get(el.accordionCfg.currentPanel),
									el.accordionCfg.panels.get(el.accordionCfg.currentPanel)
								]
							);
					    }
					    el.accordionCfg.currentPanel = this.accordionPos;

					}
				)
				.eq(0)
                .end();




			    el.accordionCfg.headers
				.each(
					function(nr) {
					    this.accordionPos = nr;
					}
				)
				.hover(
					function() {
					    jQuery(this).addClass(el.accordionCfg.hoverClass);
					},
					function() {
					    jQuery(this).removeClass(el.accordionCfg.hoverClass);
					}
				)
				.bind(
					'click',
					function(e) {

					    if (el.accordionCfg.currentPanel == this.accordionPos)
					        return;
					    var nextPanel = el.accordionCfg.panels
							.eq(this.accordionPos)
							.css({
							    height: 0,
							    display: 'block'
							});
					    el.accordionCfg.headers
							.eq(el.accordionCfg.currentPanel)
							.removeClass(el.accordionCfg.activeClass)
							.end()
							.eq(this.accordionPos)
							.addClass(el.accordionCfg.activeClass);

					    el.accordionCfg.panels
						.eq(el.accordionCfg.currentPanel)
							.animate(
								{ height: 0 },
								{
								    duration: el.accordionCfg.speed,
								    step: function(curr) {
								        nextPanel.css('height', el.accordionCfg.panelHeight - curr + 'px');
								    },
								    complete: function() {
								        this.style.display = 'none';
								        if (el.accordionCfg.onHide) {
								            el.accordionCfg.onHide.apply(el, [this]);
								        }
								    }
								}
							);

					    if (el.accordionCfg.onClick) {
					        el.accordionCfg.onClick.apply(
								el,
								[
									this,
									el.accordionCfg.panels.get(this.accordionPos),
									el.accordionCfg.headers.get(el.accordionCfg.currentPanel),
									el.accordionCfg.panels.get(el.accordionCfg.currentPanel)
								]
							);
					    }
					    el.accordionCfg.currentPanel = this.accordionPos;

					}
				)
				.eq(0)
				.addClass(el.accordionCfg.activeClass)
				.end();
			    jQuery(this)
					.css('height', jQuery(this).css('height'))
					.css('overflow', 'hidden');


			}
		);
    }
};

jQuery.fn.Accordion = jQuery.iAccordion.build;
