
/* ~/_ui/js/lib/accordion_base.js */
var Accordion = Class.create({
    version: "1.0",
    initialize: function(options) {
        // option defaults
        this.options = Object.extend({
            containerId: "accordion",
            tabSelector: "div#accordion div.tab",
            triggerSelector: "div#accordion div.trigger",
            drawerSelector: "div#accordion div.drawer",
            eventType: "click",
            defaultOpenTab: 0
        }, options || {});

        // accordion parts
        this.container = $(this.options.containerId);
        this.tabs = $$(this.options.tabSelector);
        this.triggers = $$(this.options.triggerSelector);
        this.drawers = $$(this.options.drawerSelector);
        this.accordionId = this.options.containerId;

        if (this.tabs.length == 0) {
            return;
        }

        if (this.options.animator) {
            this.animator = this.options.animator(this);
        }

        // set the state of all tabs to open
        this.tabs.each(function(currentTab) {
            currentTab._open = true;
        });

        // check query string for default tab
        this.readQueryString();

        this.readTabMarkedOpenByDefault();

        // quick close all tabs except default (no parallel event fired, therefore no animation)
        this.closeOtherTabs(this.tabs[this.options.defaultOpenTab], "quick");
    },
    readQueryString: function() {
        var originalDefaultOpenTab = this.options.defaultOpenTab;
        this.options.defaultOpenTab = window.location.search.toQueryParams()[this.accordionId];
        if (typeof (this.tabs[this.options.defaultOpenTab]) == "undefined") {
            this.options.defaultOpenTab = originalDefaultOpenTab;
        }
    },
    readTabMarkedOpenByDefault: function() {
        var originalDefaultOpenTab = this.options.defaultOpenTab;

        try {
            this.options.defaultOpenTab = this.tabs.indexOf($$("div#accordion div.tabOpen").first());
        } catch (ex) { }

        if (typeof (this.tabs[this.options.defaultOpenTab]) == "undefined") {
            this.options.defaultOpenTab = originalDefaultOpenTab;
        }
    },
    openTab: function(tab) {
        if (tab._open) { return; }
        tab.removeClassName("closed").addClassName("open");
        tab._open = true;
        // tab.fire(this.accordionId+"_tab:opened");

        var tabToOpen = tab;

        var drawerToOpen = this.drawers[this.tabs.indexOf(tabToOpen)];

        new Effect.Morph(
			drawerToOpen, {
			    style: { height: drawerToOpen._height + "px" },
			    duration: 1,
			    transition: Effect.Transitions.sinoidal,
			    queue: {
			        position: 'end',
			        scope: this.accordionId,
			        limit: 10
			    },
			    beforeStart: function() {
			        this.currentlyAnimating = true;
			    } .bind(this),
			    afterFinish: function() {
			        this.currentlyAnimating = false;
			    } .bind(this)
			}
		);
    },
    closeTab: function(tab) {
        if (!tab._open) { return; }
        tab.removeClassName("open").addClassName("closed");
        tab._open = false;
        // tab.fire(this.accordionId+"_tab:closed");
        var tabToClose = tab;
        var drawerToClose = this.drawers[this.tabs.indexOf(tabToClose)];

        new Effect.Morph(
			drawerToClose, {
			    style: { height: "0px" },
			    duration: 1,
			    transition: Effect.Transitions.sinoidal,
			    queue: {
			        position: 'end',
			        scope: this.accordionId,
			        limit: 10
			    },
			    beforeStart: function() {
			        this.currentlyAnimating = true;
			    } .bind(this),
			    afterFinish: function() {
			        this.currentlyAnimating = false;
			    } .bind(this)
			}
		);
    },
    closeOtherTabs: function(tabToOpen, type) {
        // find all open tabs
        var currentlyOpenTabs = this.tabs.findAll(function(currentTab) {
            return currentTab._open;
        });

        // close each open tab
        currentlyOpenTabs.each(function(currentTab) {
            currentTab.removeClassName("open").addClassName("closed");
            currentTab._open = false;
        });

        // set active tab to open
        tabToOpen.removeClassName("closed").addClassName("open");
        tabToOpen._open = true;

        // if type is quick, fire initialization event
        if (type == "quick") {
            //this.container.fire(this.accordionId+"_accordion:initialized",{inactiveTabs: currentlyOpenTabs, activeTab: tabToOpen});			
            var activeTab = tabToOpen;
            var inactiveTabs = currentlyOpenTabs;

            this.drawers.each(function(currentDrawer) {
                currentDrawer._height = currentDrawer.getHeight();
                currentDrawer.setStyle({ overflow: "hidden" });
            } .bind(this));

            // set inactive tabs drawer height to 0px to appear closed and for smoothness in animation
            inactiveTabs.each(function(currentTab) {
                this.drawers[this.tabs.indexOf(currentTab)].setStyle({
                    height: "0px"
                });
            } .bind(this));

            // set active tab drawer height to it's original height for smoothness in animation
            this.drawers[this.tabs.indexOf(activeTab)].setStyle({
                height: this.drawers[this.tabs.indexOf(activeTab)]._height + "px"
            });

            // if type is not quick, fire parallel event
        } else {
            // tabToOpen.fire(this.accordionId+"_tab:parallel",{tabToClose: currentlyOpenTabs});

            var tabToOpen = tabToOpen;
            var tabToClose = currentlyOpenTabs.first();
            var drawerToOpen = this.drawers[this.tabs.indexOf(tabToOpen)];
            var drawerToClose = this.drawers[this.tabs.indexOf(tabToClose)];

            new Effect.Parallel([
			        new Effect.Morph(
				        drawerToOpen, {
				            style: { height: drawerToOpen._height + "px" },
				            duration: 1,
				            transition: Effect.Transitions.sinoidal,
				            beforeStart: function() {
				                this.currentlyAnimating = true;
				            } .bind(this),
				            afterFinish: function() {
				                this.currentlyAnimating = false;
				            } .bind(this)
				        }
			        ),
			        new Effect.Morph(
				        drawerToClose, {
				            style: { height: "0px" },
				            duration: 1,
				            transition: Effect.Transitions.sinoidal,
				            beforeStart: function() {
				                this.currentlyAnimating = true;
				            } .bind(this),
				            afterFinish: function() {
				                this.currentlyAnimating = false;
				            } .bind(this)
				        }
			        )
			        ], {
			            sync: true,
			            queue: {
			                position: 'end',
			                scope: this.accordionId,
			                limit: 10
			            }
			        });
        }
    }
});

Accordion.Controller = Class.create(Accordion, {
	initialize: function($super, options){
		// call superclass's initialize
		$super(options);

		// add event handling
		this.triggers.invoke("observe", this.options.eventType, this.getActivatedTab.bindAsEventListener(this));			
	},
	getActivatedTab: function(e){
		var activatedTrigger = Event.findElement(e, this.options.triggerSelector);
		var activatedTab = this.tabs[this.triggers.indexOf(activatedTrigger)];
		this.manageActivatedTab(activatedTab);
	},
	manageActivatedTab: function(activatedTab){
		// if tab is closed, close other tabs and open it, if it is open, do nothing.
		if(!activatedTab._open){ this.closeOtherTabs(activatedTab); }	
	},
	getCurrentTab: function(){
		return this.tabs.find(function(currentTab){
			return currentTab._open;
		});
	},
	getNextTab: function(){
		var currentTab = this.getCurrentTab();
		var currentIndex = this.tabs.indexOf(currentTab);
		if (currentIndex < this.tabs.length-1){
			return this.tabs[currentIndex+1];
		} else {
			return "Currently open tab is the last tab.";
		}
	},
	getPreviousTab: function(){
		var currentTab = this.getCurrentTab();
		var currentIndex = this.tabs.indexOf(currentTab);
		if (!currentIndex == 0){
			return this.tabs[currentIndex-1];;					
		} else {
			return "Currently open tab is the first tab.";
		}
	}	
});
/* ~/_ui/js/lib/accordion_multi-tab-all-close.js */
Accordion.Controller.MultiTabAllClose = Class.create(Accordion.Controller, {
	manageActivatedTab: function(activatedTab){
		// if tab is open, close it, if tab is closed, open it.
		activatedTab._open ? this.closeTab(activatedTab) : this.openTab(activatedTab);		
	},
	getCurrentTab: function(){
		return "MultiTab Controller does not support this function.";
	},
	getNextTab: function(){
		return "MultiTab Controller does not support this function.";
	},
	getPreviousTab: function(){
		return "MultiTab Controller does not support this function.";
	}
});