/**
 * Sets up the Accordion stuff on the Landing page
 *
 * Does Not use Figment directly, but does feel the effects of it's importing
 * mechanisms
 * @requires Disney.WDPRO.IBC.Dates
 * @todo: Address dependency issue and then change back to use onDOMReady
 */
YAHOO.namespace("Disney.WDPRO.IBC.ProductSelection");
(function() {
    /* Variable Declarations {{{*/
    var self = YAHOO.Disney.WDPRO.IBC.ProductSelection,
        Dom = YAHOO.util.Dom,
        $ = YAHOO.util.Dom.get,
        Anim = YAHOO.util.Anim,
        CustomEvent = YAHOO.util.CustomEvent,
        Event = YAHOO.util.Event;

    // brower detection
    var isOpera = YAHOO.env.ua.opera,
        isSafari = YAHOO.env.ua.webkit,
        isGecko = YAHOO.env.ua.gecko,
        isIE = YAHOO.env.ua.ie;

    // All of the accessed IDs
    var ids = {
        modules: [
            "TicketStore_Module",
            "TravelDates_Module",
            "PartyMix_Module",
            "ResortSelection_Module"
        ],
        productSelectionSections: "productSelectionSections",
        accordionHeads: [
            "productSelectionHeading_RT",
            "productSelectionHeading_ROOM",
            "productSelectionHeading_PRM",
            "productSelectionHeading_PRT"
        ],
        modifyTravelContainer: "ModifyTravelContainer",
        continueButton: "continue"
    };

    // For each path type, which modules should be visible
    var availableModules = function(m) {
        return {
            RT: {
                modules: [m[0]],
                radioButton: "productSelection_RT_ProductSelectBtn"
            },
            ROOM: {
                modules: [m[1], m[2], m[3]],
                radioButton: "productSelection_ROOM_ProductSelectBtn"
            },
            PRM: {
                modules: [m[1], m[2], m[3]],
                radioButton: "productSelection_PRM_ProductSelectBtn"
            },
            PRT: {
                modules: [m[1], m[2], m[3]],
                radioButton: "productSelection_PRT_ProductSelectBtn"
            }
        };
    }(ids.modules);

    // All of the accessed class names
    var classnames = {
        show: "openedState",
        hide: "closedState",
        productSelectionButton: "productSelectionBtn",
        selected: "selected"
    };
    /* END Variable Declarations }}}*/

    /* Helper Iterators {{{*/

    // The function passed in should will be executed for each element in the
    // collection of IDs
    var withEachElement = function(collectionOfIds, func) {
        for (var i=0; i != collectionOfIds.length; i++) {
            var elem = $(collectionOfIds[i]);
            if (elem !== null) {
                func(elem);
            }
            delete elem;
        }
    };

    var withEachAccordionHeading = function(func) {
        withEachElement(ids.accordionHeads, func);
    };

    var withEachSelectedAccordionHeading = function(func) {
        withEachAccordionHeading(function(elem) {
            if (Dom.hasClass(elem, classnames.selected)) {
                func(elem);
            }
        });
    };

    var withEachUnselectedAccordionHeading = function(func) {
        withEachAccordionHeading(function(elem) {
            if (!Dom.hasClass(elem, classnames.selected)) {
                func(elem);
            }
        });
    };
    /* END Helper Iterators }}}*/

    self.addEventListenersToAccordionHeadings = function() {
        withEachUnselectedAccordionHeading(function(elem) {
            Event.addListener(elem, "click", self.handleClickEventForAccordionHeadings, elem, false);
        });
        withEachSelectedAccordionHeading(function(elem) {
            Event.addListener(elem, "click", self.handleClickForCurrentlySelectedAccordionHeadings, elem, false);
        });
    };

    self.removeEventListenersToAccordionHeadings = function() {
        withEachUnselectedAccordionHeading(function(elem) {
            Event.removeListener(elem, "click", self.handleClickEventForAccordionHeadings);
        });
        withEachSelectedAccordionHeading(function(elem) {
            Event.removeListener(elem, "click", self.handleClickForCurrentlySelectedAccordionHeadings);
        });
    };

    self.getRoomOnlyAccordionHeadId = function() {
        return ids.accordionHeads[1];
    };

    self.getRoomDineAccordionHeadId = function() {
        return ids.accordionHeads[2];
    };

    self.getPackagesAccordionHeadId = function() {
        return ids.accordionHeads[3];
    };

    /**
     * Formatting method to get a string rep for the calendar
     */
    var dateOutput = function(objDate) {
        var intMonth = objDate.getMonth() + 1;
        var strMonth = intMonth;
        var intDate = objDate.getDate();
        var strDate = intDate;
        var intYear = objDate.getFullYear();
        return strMonth + "/" + strDate + "/" + intYear;
    };

    /**
     * A simple method to get the height of the travel container
     */
    var getModifyTravelContainerHeight = function() {
        var region = Dom.getRegion(ids.modifyTravelContainer);
        return region.bottom - region.top;
    };

    /**
     * A custom event used after the product selection updates
     * I know, cryptic naming.
     */
    self.afterUpdateProductSelection = new CustomEvent('afterUpdateProductSelection');

    /**
     * Simply, do nothing if this heading is clicked
     */
    self.handleClickForCurrentlySelectedAccordionHeadings = function(evt, obj) {
        Event.stopEvent(evt);
        obj.blur();
    };

    /**
     * Event listener for when a heading is clicked.
     * This is responsible for starting the animation cycle by closing the
     * currently selected pane.
     */
    self.handleClickEventForAccordionHeadings = function(evt, obj) {
        Event.stopEvent(evt);
        obj.blur();

        if (!Dom.hasClass(obj, 'disabled')) {

            // Clear all event listeners
            self.removeEventListenersToAccordionHeadings();

            var container = $(ids.modifyTravelContainer);
            var parentContainer = container.parentNode;
            var containerHeight = getModifyTravelContainerHeight();

            var closingAnimation = new Anim(parentContainer, {
                        height: { from: containerHeight,  to: 0 },
                        opacity: { from: 1, to: 0 }
                    }, 0.36);
            closingAnimation.onComplete.subscribe(self.closingAnimationCallback, obj);
            closingAnimation.onStart.subscribe(self.startClosingAnimationCallback);
            closingAnimation.animate();

            delete container;
            delete parentContainer;
            
        }
    };

    /**
     * In order for the blinding up to happen, the overflow must be set to
     * hidden
     */
    self.startClosingAnimationCallback = function(evt, results) {
        withEachAccordionHeading(function(elem) {
            var definition = Dom.getNextSibling(elem);
            Dom.setStyle(definition, "overflow", "hidden");
            delete definition;
        });
    };

    /**
     * Closing animation callback.  This removes the selected status from the
     * previously selected heading and assigns it to the currently selected
     * one.  It also re-initializes the calendar objects using the stored biz
     * rules and starts the opening animation cycle. To update the travel
     * container, remove the travel container from it's current parent and
     * attach it to the selected dd and then start the animation to show it
     */
    self.closingAnimationCallback = function(evt, results, selectedHeading) {
        // checks to see if selectedHeading is null, which only occurs on
        // Cast and Agent TAAP, when there is NO heading.
        if (selectedHeading !== null){
            withEachSelectedAccordionHeading(function(elem) {
                Dom.removeClass(elem, "selected");
            });

            // Annotate the selected heading and re-add the listeners
            Dom.addClass(selectedHeading, "selected");

            // update module display
            var selectedPath = Dom.getFirstChildBy(selectedHeading, function(el) {
                        return Dom.hasClass(el, classnames.productSelectionButton);
                    }).value;
            var selectedAvailableModules = availableModules[selectedPath];

            withEachElement(ids.modules, function(elem) {
                Dom.replaceClass(elem, classnames.show,classnames.hide);
            });

            withEachElement(selectedAvailableModules.modules, function(elem) {
                Dom.replaceClass(elem, classnames.hide, classnames.show);
            });

            if (selectedPath !== 'RT') {
                var IBCDates = Disney.WDPRO.IBC.Dates;
                var objArrivalDate = $('travelDates_Arrival');
                var objDepartureDate = $('travelDates_Departure');

                if (IBCDates !== undefined && objArrivalDate !== null && objDepartureDate !== null) {
                    objArrivalDate.value = dateOutput(new Date(IBCDates.resetDefaultArrivalDate(selectedPath)));
                    objDepartureDate.value = dateOutput(new Date(IBCDates.resetDefaultDepartureDate(objArrivalDate.value,selectedPath)));
                }
                delete objArrivalDate;
                delete objDepartureDate;
            }else{

                /*
                if booking path does not allow for Room Options (RO Path)
                run a check on modules, ensure it has openedState class assigned to it
                this is especially necessary for ResortSelection_Module
                however, does not hurt to include on other modules -- rather than hardcode anything here, just add class to all modules
                */
                for(var i = 0; i < ids.modules.length; i++)
                {
                    var el = Dom.get(ids.modules[i]);
                    if(Dom.hasClass  ( el , classnames.show ) !== true)
                    {
                        Dom.addClass  ( el , classnames.show );
                    }
                }

            }

            $(selectedAvailableModules.radioButton).checked = true;
        }
        var container = $(ids.modifyTravelContainer);

        Dom.addClass(container, classnames.hide);
        withEachSelectedAccordionHeading(function(elem) {
            var currentContainerParent = container.parentNode;
            var definition = Dom.getNextSibling(elem);

            currentContainerParent.removeChild(container);
            definition.appendChild(container);

            self.afterUpdateProductSelection.fire(elem);

            // Set the noAsync class if it's tickets
            if (ids.accordionHeads[0] === elem.id) {
                Dom.addClass(ids.continueButton, "noAsync");
            } else {
                Dom.removeClass(ids.continueButton, "noAsync");
            }

            delete currentContainerParent;
            delete definition;
        });
        Dom.removeClass(container, classnames.hide);

        var parentContainer = container.parentNode;
        var containerHeight = getModifyTravelContainerHeight();
        var openingAnimation = new Anim(parentContainer, {
                    height: { from: 0,  to: containerHeight },
                    opacity: { from: 0, to: 1 }
                }, 0.36);
        openingAnimation.onComplete.subscribe(self.openingAnimationCallback);
        openingAnimation.animate();

        delete container;
        delete parentContainer;
        
        // Calls travel date method to update travel dates if the user changes the Path Type
        Disney.WDPRO.IBC.TravelDates.Events.EVENT_useStoredStateCookieDates();
        
        
        
    };

    /**
     * Call back for opening animations
     *
     * Re-attaches event listeners and resets the dd height so that there's no
     * clipping
     */
    self.openingAnimationCallback = function() {
        self.addEventListenersToAccordionHeadings();

        var parentContainer = $(ids.modifyTravelContainer).parentNode;
        Dom.setStyle(parentContainer, "height", "auto");
        Dom.setStyle(parentContainer, "overflow", "visible");
        // Yahoo could really stand to get a removeStyle function
        if (isIE) {
            parentContainer.style.filter = null;
        }
        delete parentContainer;
    };

    /**
     * Preps the container dd tags and moves the modify trave stuff into place
     */
    self.init = function() {
        // Set the default height and opacity for the definition for the
        // modifyTravelContainer
        withEachAccordionHeading(function(elem) {
            var definition = Dom.getNextSibling(elem);
            Dom.setStyle(definition, "height", 0);
            Dom.setStyle(definition, "opacity", 0);
            Dom.setStyle(definition, "zoom", 1);
            Dom.setStyle(definition, "overflow", "hidden");
            delete definition;
        });

        if ($(ids.productSelectionSections) !== null){
            withEachSelectedAccordionHeading(function(elem) {
                self.closingAnimationCallback(null,null,elem);
            });
        } else {
            self.closingAnimationCallback(null,null,null);
        }
    };

    // Rev this baby up
    Figment.EntryPoint.add({main: function() {
        self.init();

        // Really?  Does this belong here? Oh well.
        // if anything but US is selected, hide the state dropdown
        var countryDropDown = $("ticketWhereTraveling_Country");
        if (countryDropDown !== null) {
            Event.addListener(
                countryDropDown,
                "change",
                function(evt, obj) {
                    var stateDropDown = $('ticketWhereTraveling_StateField');
                    if (obj.value !== 'US') {
                        stateDropDown.style.display='none';
                    } else {
                        stateDropDown.style.display='block';
                    }
                    delete stateDropDown;
                },
                countryDropDown);
        }
        delete countryDropDown;
    }});
})();

