/* search results api */
(function() {
    // ### create local references/shortcuts (also helps compression) ### //
    var yuiDom = YAHOO.util.Dom;
    var yuiEvent = YAHOO.util.Event;
    var yuiAnim = YAHOO.util.Anim;
    var yuiEasing = YAHOO.util.Easing;
    var yuiLang = YAHOO.lang;
    var yuiJson = YAHOO.lang.JSON;
    var yuiCustomEvent = YAHOO.util.CustomEvent;
    var favoriteEvent = SW.customEvent.Favorite;
    var Url = SW.tools.Url;
    var Cookie = SW.tools.Cookie;
    var TabManager = SW.widget.PropertyDetails.TabManager;
    var FilterManager = SW.widget.FilterManager;

    // Defining all objcets here to avoid strict js warnings
    var PropertyManager,MapManager,PageManager,CountManager,MessageManager,FavoritesManager;

    // customEvent could be moved to /js/lib/starwood/customEvent/searchResults.js, but that might be overkill.
    // technically the customEvent should not be tied to this implementation, but for all intents and purposes and might as well be.
    var resultsEvent = SW.customEvent.SearchResults = {
    // displayProperties is passed to each handler
        onDisplay:new yuiCustomEvent("display", this, false, yuiCustomEvent.FLAT),
        toggleFilterEvent:new yuiCustomEvent("toggleFilterEvent", this, false, yuiCustomEvent.FLAT),
        toggleMapEvent:new yuiCustomEvent("toggleMapEvent", this, false, yuiCustomEvent.FLAT),
        sortChangeEvent:new yuiCustomEvent("sortChangeEvent", this, false, yuiCustomEvent.FLAT),
        payWithChangeEvent:new yuiCustomEvent("payWithChangeEvent", this, false, yuiCustomEvent.FLAT)
    };

    // ### PropertyManager ### //
    PropertyManager = (function() {
        // private vars
        var initialized = false;
        var settings = {
            refineMessageDelay:1000,
            loadingMessageDelay:1250,
            defaultSortType:"availability",
            sortCriteriaMap:{
                availability:["isCurrentBrand","hasCurrentPayWithType","isBookable","distance","city","name"],
                distance:["isCurrentBrand","distance","hasCurrentPayWithType","isBookable","city","name"],
                priceAsc:["isCurrentBrand","hasCurrentPayWithType","isBookable","currentPayWithAmount","name"],
                priceDesc:["isCurrentBrand","hasCurrentPayWithType","isBookable","currentPayWithAmount",-1,"name"],
                name:["isCurrentBrand","name"]
            }
        };
        var allProperties = [];
        var activeProperties = [];
        var searchType = null;
        var lastSort = null;
        var lastFilter = null;
        var lastPayWithType = null;

        var refineTimeout = null;
        // private methods
        function showRefine(show) {
            if (show) {
                yuiDom.addClass("searchResultsContainer", "refining");
            } else {
                yuiDom.removeClass("searchResultsContainer", "refining");
            }
        }
        function hideProperties() {
            allProperties.forEach(function(property) {
                property.isShowing = false;
                yuiDom.removeClass(property.container, "show");
            });
        }
        function showProperties() {
            var count = 1;
            activeProperties.forEach(function(property) {
                property.isShowing = true;
                yuiDom.addClass(property.container, "show");
                property.resultCount.innerHTML = count + ".";
                property.parentContainer.appendChild(property.container);
                count++;
            });
            CountManager.update();
            resultsEvent.onDisplay.fire(activeProperties);
        }
        function allowSort(sortType, forceResort){
            // if is alternate availability page, do not allow sorting
            // else if forceResort or sort has changed, allow sorting
            // else no resort
            return ( searchType != "alternate" && ( lastSort != sortType || forceResort) );
        }
        function sortProperties(sortType, forceResort) {
            // set cookie
            sortType = sortType || settings.defaultSortType;
            if (allowSort(sortType, forceResort)) {
                Cookie.set("searchsort_" + SW.local.skinCode, sortType);
                activeProperties.objectSort.apply(activeProperties, settings.sortCriteriaMap[sortType]);
                lastSort = sortType;
                return true;
            }
            return false;
        }
        function filterProperties(criteria) {
            var currentFilter = "";
            if (criteria) {
                currentFilter = criteria.join();
            }
            if (lastFilter == currentFilter) {
                // note: not likely to get here, but this avoids extra filting
                return false;
            }
            if (!criteria) {
                activeProperties = Array.Copy(allProperties);
            } else {
                criteria.forEach(function(filter) {
                    allProperties.setFilter.apply(allProperties, filter);
                });
                activeProperties = allProperties.objectFilter();
                // could displayProperties be used here?
            }
            lastFilter = currentFilter;
            return true;
        }
        function changePayWith(type) {
            // type: cash, cashPoints, starpoints
            if (lastPayWithType == type) {
                return false;
            }
            var hasType = "has" + type;
            allProperties.forEach(function(property) {
                property.hasCurrentPayWithType = property[hasType];
                property.currentPayWithAmount = property[type];
            });
            lastPayWithType = type;
            return true;
        }

        function initialSort() {
            var sortType = Cookie.get("searchsort_" + SW.local.skinCode);
            if (sortType) {
                var select = document.getElementById("sortBy");
                for (var i = 0; i < select.options.length; i++) {
                    if (select.options[i].value == sortType) {
                        select.options[i].selected = true;
                        break;
                    }
                }
            }
            sortProperties(sortType);
        }
        function getPropertyById(propertyId){
            for(var i = 0; i < allProperties.length; i++){
                if(allProperties[i].propertyId == propertyId){
                    return allProperties[i];
                }
            }
            return null;
        }
        function removeProperty(property){
            if(property){
                var anim = new yuiAnim(property.container,{opacity:{to:0}},0.6,yuiEasing.easeNone);
                anim.onComplete.subscribe(function(){
                    property.parentContainer.removeChild(property.container);
                    allProperties.remove(property);
                    activeProperties.remove(property);
                    showProperties();
                });
                anim.animate();
            }
        }

        // helper methods to scrub html for data
        var getInputData = SW.tools.Html.getDataFromInput;
        var getTagData = SW.tools.Html.getDataFromTag;
        // public methods
        var self = {
            initialize:function() {
                if (initialized) {
                    return;
                }
                initialized = true;
                // global info for PropertyManager
                searchType = yuiDom.get("searchResultsLayoutContainer").className;

                // parse property results
                var results = yuiDom.getElementsByClassName("property", "div", "searchResults");
                var resultsPrimary = yuiDom.get("resultsPrimary");
                results.forEach(function(propDiv) {
                    var cash = getTagData(propDiv, "span", "cash", "int", 0);
                    var cashPoints = getTagData(propDiv, "span", "cashPoints", "int", 0);
                    var starpoints = getTagData(propDiv, "span", "starpoints", "int", 0);
                    var spgCategory = getInputData(propDiv, "spgCategoryCode", "int", 0);
                    allProperties.push({
                    // elements
                        container:propDiv,
                        parentContainer:propDiv.parentNode,
                        resultCount:yuiDom.getElementsByClassName("resultCount", "div", propDiv)[0],

                    // strings
                        propertyId:getInputData(propDiv, "propertyId", "string", ""),
                        brandCode:getInputData(propDiv, "brandCode", "string", ""),
                        name:getTagData(propDiv, null, "propertyName", "string", ""),
                        city:getInputData(propDiv, "city", "string", ""),

                    // arrays
                        amenities:getInputData(propDiv, "matchingAmenities", "array", []),

                    // booleans
//                        isPrimary:yuiDom.isAncestor(resultsPrimary, propDiv),
                        isPrimary:getInputData(propDiv, "isCurrentBrand", "boolean", false),
                        isFavorite:yuiDom.hasClass(propDiv, "favorite"),
                        isOpenHot:yuiDom.hasClass(propDiv, "openHot"),
                        isCurrentBrand:getInputData(propDiv, "isCurrentBrand", "boolean", false),
                        isSPG:(spgCategory > 0),
                        isBookable:getInputData(propDiv, "isBookable", "boolean", false),
                        hascash:(cash > 0),
                        hascashPoints:(cashPoints > 0),
                        hasstarpoints:(starpoints > 0),

                    // numbers
                        category:spgCategory,
                        cash:cash,
                        cashPoints:cashPoints,
                        starpoints:starpoints,
                        distance:getInputData(propDiv, "distance", "float", 0),

                    // for sorting (cash is default pay with type)
                        hasCurrentPayWithType:(cash > 0),
                        currentPayWithAmount:cash,

                    // omniture specific attributes
                        ratePlanId:getInputData(propDiv, "ratePlanId", "string", ""),
                        currencyCode:getInputData(propDiv, "currencyCode", "string", ""),
                        activeStatus:getInputData(propDiv, "activeStatus", "string", ""),
                        isDisplayRate:getInputData(propDiv, "isDisplayRate", "boolean", false)
                    });
                });


                activeProperties = Array.Copy(allProperties);

                initialSort();
                showProperties();
                setTimeout(function() {
                    yuiDom.removeClass("searchResultsContainer", "loading");
                }, settings.loadingMessageDelay);


                //this need to be optimized, and remove dependancy on "isCurrentBrand" being the first item in the array
                if (yuiDom.get("brandPriority").value == "false") {
                    settings.sortCriteriaMap.availability.splice(0,1);
                    settings.sortCriteriaMap.distance.splice(0,1);
                    settings.sortCriteriaMap.priceAsc.splice(0,1);
                    settings.sortCriteriaMap.priceDesc.splice(0,1);
                    settings.sortCriteriaMap.name.splice(0,1);
                }
            },
            removeProperty:function(property){
                if( yuiLang.isString(property) ){
                    property = getPropertyById(property);
                }
                if(property){
                    removeProperty(property);
                }
            },

            sort:function(sortType) {
                if (sortProperties(sortType)) {
                    self.display();
                }
            },
            filter:function(criteria) {
                if (filterProperties(criteria)) {
                    if (criteria) {
                        self.displayWithRefineMessage();
                    } else {
                        self.display();
                    }
                }
            },
            setPayWith:function(type) {
                if (changePayWith(type)) {
                    sortProperties(lastSort, true);
                    self.display();
                }
            },
            display:function() {
                hideProperties();
                showProperties();
            },
            displayWithRefineMessage:function() {
                showRefine(true);
                if(refineTimeout != null){
                    clearTimeout(refineTimeout);
                    refineTimeout = null;
                }
                refineTimeout = setTimeout(function() {
                    hideProperties();
                    showProperties();
                    showRefine(false);
                }, settings.refineMessageDelay);
            },
            configure:function(config) {
                var prop;
                for (prop in config) {
                    if (config.hasOwnProperty(prop) && settings.hasOwnProperty(prop)) {
                        settings[prop] = config[prop];
                    }
                }
            },
            updateProperty:function(property,config){
                if(yuiLang.isString(property)){
                    property = getPropertyById(property);
                }
                if(!yuiLang.isObject(property)){
                    return;
                }
                for(var prop in config){
                    if(property.hasOwnProperty(prop)){
                        property[prop] = config[prop];
                    }
                }

            },
            getProperty:function(propertyId){
                return getPropertyById(propertyId)
            },
            getActiveProperties:function() {
                return activeProperties;
            },
            getAllProperties:function() {
                return allProperties;
            }
        };
        return self;
    })();

    // ### MapManager ### //
    MapManager = (function() {
        // private
        var initialized = false;


        // public
        var self = {
            initialize:function() {
                if (initialized) {
                    return;
                }
                initialized = true;
            }

        };
        return self;
    })();


    /*
    Sample usage for CountManager
        <span class="totalResults">25</span> Hotels were found
        <span class="totalDisplayed">20</span> Results match your criteria
        <span class="currentBrandTotal">8</span> Westins were found
        <span class="otherStarwoodsTotal">17</span> Starwood Hotels were found
        <span class="currentBrandDisplayed">5</span> Westins match your criteria
        <span class="otherStarwoodsDisplayed">15</span> Starwood hotels match your criteria
        <span class="totalFavorites">8</span> Hotels are your favorites
        <span class="favoritesDispalyed">4</span> favorites match your criteria
    */
    // ## CountManager ## //
    var CountManager = (function() {
        // private
        var initialized = false;
        var CLASS_NAMES_TO_VALUES = {
            totalResults:0,
            totalDisplayed:0,
            currentBrandTotal:0,
            currentBrandDisplayed:0,
            otherStarwoodsTotal:0,
            otherStarwoodsDisplayed:0,
            totalFavorites:0,
            favoritesDispalyed:0
        };
        function resetCounts() {
            for (var key in CLASS_NAMES_TO_VALUES) {
                if (CLASS_NAMES_TO_VALUES.hasOwnProperty(key)) {
                    CLASS_NAMES_TO_VALUES[key] = 0;
                }
            }
        }
        function updateCounts() {
            var allProperties = PropertyManager.getAllProperties();
            // total
            CLASS_NAMES_TO_VALUES.totalDisplayed = PropertyManager.getActiveProperties().length;
            CLASS_NAMES_TO_VALUES.totalResults = allProperties.length;
            allProperties.forEach(function(property) {
                if (property.isShowing) {
                    // displayed totals
                    if (property.isFavorite) {
                        CLASS_NAMES_TO_VALUES.favoritesDispalyed++;
                    }
                    if (property.isCurrentBrand) {
                        CLASS_NAMES_TO_VALUES.currentBrandDisplayed++;
                    } else {
                        CLASS_NAMES_TO_VALUES.otherStarwoodsDisplayed++;
                    }
                }
                // totals
                if (property.isFavorite) {
                    CLASS_NAMES_TO_VALUES.totalFavorites++;
                }
                if (property.isCurrentBrand) {
                    CLASS_NAMES_TO_VALUES.currentBrandTotal++;
                } else {
                    CLASS_NAMES_TO_VALUES.otherStarwoodsTotal++;
                }
            });
        }
        function displayCounts(){
            var spans;
            var container = yuiDom.get("searchResultsLayoutContainer");
            for (var key in CLASS_NAMES_TO_VALUES) {
                if (CLASS_NAMES_TO_VALUES.hasOwnProperty(key)) {
                    yuiDom.getElementsByClassName(key, "span", container).forEach(function(span) {
                        span.innerHTML = CLASS_NAMES_TO_VALUES[key];
                    });
                }
            }
        }
        // public
        var self = {
            initialize:function() {
                if (initialized) {
                    return;
                }
                initialized = true;
            },
            update:function() {
                resetCounts();
                updateCounts();
                displayCounts();
            },
            getValue:function(className) {
                return CLASS_NAMES_TO_VALUES[className];
            }
        };
        return self;
    })();

    // ### PageManager - handle general dom, event handler stuff (tabs, nav bar interactions) ### //
    PageManager = (function() {
        // private
        var initialized = false;

        function removeAllFilters() {
            FilterManager.removeAllFilters();
            PropertyManager.filter();
        }
        function closeFilter() {
            yuiDom.removeClass("filterButton", "active");
            yuiDom.removeClass("filterContainer", "show");
            removeAllFilters();
        }
        function showFilter() {
            yuiDom.addClass("filterButton", "active");
            yuiDom.addClass("filterContainer", "show");
            // lazy load... only initialize FilterManger if user interacts with it
            FilterManager.initialize();
            FilterManager.updateDisplay();
        }
        function showMap() {
            // lazy load... only initialize MapManger if user interacts with it
            MapManager.initialize();
            yuiDom.addClass("mapButton", "active");
            yuiDom.addClass("mapContainer", "show");
        }
        function closeMap() {
            yuiDom.removeClass("mapButton", "active");
            yuiDom.removeClass("mapContainer", "show");
        }
        function showFilterOnLoad() {
            var selectedFilterType = Url.getParameter(document.location.href, "filterType");
            // amenity, brand, category
            var selectedFilterCriteria = Url.getParameter(document.location.href, "filterCriteria");
            // comma "," delimited
            if (selectedFilterType && selectedFilterCriteria) {
                FilterManager.initialize();
                FilterManager.applyFilterManual(selectedFilterType, selectedFilterCriteria.split(","));
                PageManager.showFilter();
            }
        }
        function selectTabOnLoad() {
            var type = yuiDom.get("payWith").value;
            TabManager.setAll(type);
            PropertyManager.setPayWith(type);
        }
        // event handlers //
        function selectSortCriteriaBridge() {
            PropertyManager.sort(yuiDom.get("sortBy").value);
            searchResultsMap.resetPropertyContentArray();
            resultsEvent.sortChangeEvent.fire(yuiDom.get("sortBy").value);
        }
        function selectPayWithBridge() {
            var type = yuiDom.get("payWith").value;
            TabManager.setAll(type);
            PropertyManager.setPayWith(type);
            resultsEvent.payWithChangeEvent.fire(type);
        }
        function toggleFilterBridge() {
            var isShowing = false;
            if (!yuiDom.hasClass("filterContainer", "show")) {
                showFilter();
                isShowing = true;
            } else {
                closeFilter();
            }
            resultsEvent.toggleFilterEvent.fire(isShowing);
        }
        function removeAllFiltersBridge() {
            FilterManager.removeAllFilters();
        }
        function closeFilterBridge() {
            closeFilter();
        }
        function showFilterBridge() {
            showFilter();
        }
        function toggleMapBridge() {
            var isShowing = false;
            if (!yuiDom.hasClass("mapContainer", "show")) {
                showMap();
                isShowing = true;
            } else {
                closeMap();
            }
            resultsEvent.toggleMapEvent.fire(isShowing);
        }
        function addListeners() {
            // nav bar items:
            yuiEvent.addListener("sortBy", "change", selectSortCriteriaBridge);
            yuiEvent.addListener("payWith", "change", selectPayWithBridge);
            yuiEvent.addListener("filterButton", "click", toggleFilterBridge);
//            yuiEvent.addListener("mapButton", "click", toggleMapBridge);
            yuiEvent.addListener("closeMapLink", "click", toggleMapBridge);

            // Filter items
            yuiEvent.addListener("removeFilter", "click", removeAllFiltersBridge);
            yuiEvent.addListener("closeFilter", "click", closeFilterBridge);

        }


        // public
        var self = {
            initialize:function() {
                if (initialized) {
                    return;
                }
                initialized = false;
                addListeners();
                selectTabOnLoad();
                showFilterOnLoad();
            },
            showMap:function(){
                showMap();
            }
        };
        return self;
    })();

    // todo: improve performance by only updating changed items (maintain a "last" state?)
    var MessageManager = (function(){
        // private
        var initialized = false;
        // elements are currently only read onload... if any are created dynamically, this will need to change
        var elements = {
            resultsContainer:null,
            favoritesContainers:[],
            primaryHeading:null,
            primaryNoResults:null,
            noResults:null,
            secondaryHeading:null,
            secondaryNoResults:null
        };
        // using helper method to simplify checks for null elements
        function showElement(el,show){ // not yet in use
            if(!el){
                return;
            }
            if(show){
                yuiDom.addClass(el,"show");
            }else{
                yuiDom.removeClass(el,"show");
            }
        }
        function updateFavorites(){
            var numFavorites = CountManager.getValue("favoritesDisplayed");
            elements.favoritesContainers.forEach(function(el){
                if(numFavorites >= 1){
                    showElement(el,true);
                }else{
                    showElement(el,false);
                }
            });
        }
        function updatePrimaryResults(){
            var numPrimary = CountManager.getValue("currentBrandDisplayed");
            var numSecondary = CountManager.getValue("otherStarwoodsDisplayed");
            if(numPrimary === 0){
                showElement(elements.primaryHeading,false);
                showElement(elements.primaryNoResults,true);
                if(numSecondary === 0){
                    // this code block should never execute (note: noResults element is not in source when results are returned from backend)
                    showElement(elements.primaryNoResults,false);
                    showElement(elements.noResults,true);
                }else{
                    showElement(elements.primaryNoResults,true);
                    showElement(elements.noResults,false);
                }
            }else{
                // multiple
                showElement(elements.primaryHeading,true);
                showElement(elements.primaryNoResults,false);
            }
        }
        function updateSecondaryResults(){
            var numPrimary = CountManager.getValue("currentBrandDisplayed");
            var numSecondary = CountManager.getValue("otherStarwoodsDisplayed");
            if(numSecondary === 0){
                showElement(elements.secondaryHeading,false);
            }else if(numPrimary === 0){
                // no primary, but have secondary... do not show secondary heading
                showElement(elements.secondaryHeading,false);
            }else{
                // multiple
                showElement(elements.secondaryHeading,true);
            }
        }
        function updateAllMessages(){
            updateFavorites();
            updatePrimaryResults();
            updateSecondaryResults();
        }
        // public
        var self = {
            initialize:function(){
                if(initialized){
                    return;
                }
                initialized = true;

                elements.resultsContainer = yuiDom.get("searchResultsLayoutContainer");

                elements.favoritesContainers = yuiDom.getElementsByClassName("singularFavoritesContainer","span",elements.resultsContainer);

                elements.primaryHeading = yuiDom.get("primaryHeading");
                elements.primaryNoResults = yuiDom.get("primaryNoResults");

                elements.noResults = yuiDom.get("noResultsMessage");

                elements.secondaryHeading = yuiDom.get("secondaryHeading");

                // event handlers could be tied to either public or private methods
                favoriteEvent.onAddFavorite.subscribe(self.updateFavorites);
                favoriteEvent.onRemoveFavorite.subscribe(self.updateFavorites);
                resultsEvent.onDisplay.subscribe(self.updateAllMessages);
            },
            updateAllMessages:function(){
                updateAllMessages();
            },
            updateFavorites:function(){
                updateFavorites();
            }
        };
        return self;
    })();


    // ### FavoritesManager ### //
    FavoritesManager = (function() {
        // private
        var initialized = false;
        var settings = {
            removeFromDom:false
        };

        function updateProperty(propertyId,isFavorite){
            var property = PropertyManager.getProperty(propertyId);
            if(property){
                PropertyManager.updateProperty(property,{
                    isFavorite:isFavorite
                });
                if(isFavorite){
                    yuiDom.addClass(property.container,"favorite");
                }else{
                    yuiDom.removeClass(property.container,"favorite");
                    if(settings.removeFromDom){
                        PropertyManager.removeProperty(property);
                    }
                }
            }
        }

        function addFavorite(propertyId){
            updateProperty(propertyId,true);
        }
        function removeFavorite(propertyId){
            updateProperty(propertyId,false);
        }

        // public
        var self = {
            initialize:function() {
                if (initialized) {
                    return;
                }
                initialized = true;

                // on Add/Remove of favorite, update property object and div
                favoriteEvent.onAddFavorite.subscribe(addFavorite);
                favoriteEvent.onRemoveFavorite.subscribe(removeFavorite);
            },
            configure:function(config) {
                var prop;
                for (prop in config) {
                    if (config.hasOwnProperty(prop) && settings.hasOwnProperty(prop)) {
                        settings[prop] = config[prop];
                    }
                }
            }
        };
        return self;
    })();



    // ### omniture stuff ### //
    // only one function, no need to create an object for omniture tracking
    function setOmnitureSearchParams(propertyArray) {
        var htlDmdCount = 0;
        var propArray = [];
        var productArray = [];
        if (propertyArray.length > 0) {
            for (var i = 0; i < propertyArray.length; i++) {
                var propertyResult = propertyArray[i];

                var currentPropId = propertyResult.propertyId;

                var currentRatePlanId = "BookNow";
                var currentRateAsString = "";
                var currentCurrencyCd = "";

                if (!propertyResult.activeStatus == "Active") {

                    currentRatePlanId = "NotBookable";
                    currentCurrencyCd = "";

                } else {
                    if (!propertyResult.hascash) {

                        currentRatePlanId = "NotAvail";
                        currentCurrencyCd = "";

                    } else if (propertyResult.hascash && propertyResult.isDisplayRate) {
                        if (propertyResult.cash > 0) {
                            currentRatePlanId = propertyResult.ratePlanId;
                            currentRateAsString = propertyResult.cash;
                            currentCurrencyCd = propertyResult.currencyCode;
                        }
                    }
                }
                // Any other outcome is covered by the defaults prior to this if block.

                productArray.push(";htlList-" + currentPropId + ",;htlList-" + currentPropId + "-" + currentRatePlanId);

                if (htlDmdCount <= 2) {
                    htlDmdCount++;
                    propArray.push(currentPropId + ":" + currentRateAsString + ":" + currentCurrencyCd + ":" + currentRatePlanId);
                }
            }
        }


        s.prop41 = propArray.join(",");
        // We limit the number of properties explicitly to 10 to avoid blowing up the tracking broadcast URL
        productArray.length = Math.min(productArray.length,10);
        s.products = productArray.join(",");
        s.t();
    }
    function initOmniture(){
        resultsEvent.toggleFilterEvent.subscribe(function(isShowing){
            s.products = "";
            s.prop41 = "";
            s.eVar41 = "";
            setOmniVars(s.charSet, s.server, s.channel, s.prop2, s.prop3, s.prop1, "", "Search", "Results", "Refine", isShowing);
            s.t();
        });
        resultsEvent.toggleMapEvent.subscribe(function(isShowing){
            // We fire the below two events in updateOmniture(..) function to avoid duplicate events which would blow up the count.
            // setOmniVarsYUI(s.charSet, s.server, s.channel, s.prop2, s.prop3, s.prop1, "", s.prop9,"results map", isShowing);
        });
        resultsEvent.sortChangeEvent.subscribe(function(sortKey){
            // We fire the below two events in updateOmniture(..) function to avoid duplicate events which would blow up the count.
            // setOmniVarsYUI(s.charSet, s.server, s.channel, s.prop2, s.prop3, s.prop1, "", s.prop9,"sort drop down", sortKey);
        });
        resultsEvent.payWithChangeEvent.subscribe(function(payWithKey){
            s.products = "";
            s.prop41 = "";
            s.eVar41 = "";
            setOmniVars(s.charSet, s.server, s.channel, s.prop2, s.prop3, s.prop1, "", "Search", "Results", "PayWith", payWithKey);
            s.t();
        });
        resultsEvent.onDisplay.subscribe(function(activeProperties){
            function updatePositionInBookingUrls(prop,index){
                var position = index + 1;
                if(!prop._bookingAnchors){
                    prop._bookingAnchors = yuiDom.getElementsByClassName("bookingLink","a",prop.container);
                }
                function appendPositionToAnchor(anchor){
                    anchor.href = Url.setParameter(anchor.href,"navigationPosition",position);
                }
                prop._bookingAnchors.forEach(appendPositionToAnchor);
            }
            activeProperties.forEach(updatePositionInBookingUrls);
        });

        //add in the hooks for map or sort changed by the user
        yuiEvent.addListener("sortBy", "change", updateOmnitureSortBy);
        yuiEvent.addListener("mapButton", "click", updateOmnitureMapButton);
        yuiEvent.addListener("closeMapLink", "click", updateOmnitureCloseMapLink);
    }

    function updateOmnitureSortBy() {
        var sortByValue = yuiDom.get("sortBy").value;
        var params = "item=sort&value=" + sortByValue;
        updateOmniture(params, "SortBy:" + sortByValue);
    }

    function updateOmnitureMapButton() {
        PropertyManager.display();                    
        var mapValue = (yuiDom.hasClass("mapButton", "active")) ? "open" : "close";
        var params = "item=map&value=" + mapValue;
        updateOmniture(params, "Map:" + mapValue);
    }

    function updateOmnitureCloseMapLink() {
        var params = "item=map&value=close";
        updateOmniture(params, "Map:CloseLink");
    }

    function updateOmniture(urlParams, clickedItem) {
        var url = "/ajax/siteConfigExclude.html?type=search&" + urlParams;
        var callback = {
            success:function(response) {
                var result = yuiJson.parse(response.responseText);
                var brandCode= SW.local.skinCode;
                var layoutNumber = "Exclude:" + result.data.exclude;
                var mvtPageName =  brandCode + "_" + "SearchResults";
                var localeCode = result.data.localeCode;

                if (typeof s != 'undefined') {
                    // Omniture call
                    s.eVar46 = s.prop46 = brandCode + ":SearchResults:" + layoutNumber;
                    s.products = "";
                    s.prop41 = "";
                    s.eVar41 = "";
                    // We shall replace the below clickedItem passed into the pageName with an equivalent success event in the next release.
                    // For now lets clean up the pageName to restore tracking in the original bucket.
                    setOmniVars(s.charSet, s.server, s.channel, s.prop2, s.prop3, s.prop1, "", "Search", "Results", clickedItem);
                    s.t();
                    // Offermatica call
                    if (typeof mboxUpdate == 'function') mboxUpdate(mvtPageName, 'localeCode=' + localeCode , 'layoutNumber=' + layoutNumber);
                }
            },
            failure:function() {
                //failed, but nothing to do about it
            }
        };
        var transaction = YAHOO.util.Connect.asyncRequest('GET', url, callback, null);
    }

    // ### grouping helps organize the objects ### //
    var SearchResults = {
        initialize:function() {
            // note: MapManagers is initialized when first used
            initOmniture();

            CountManager.initialize();
            PropertyManager.initialize();
            MessageManager.initialize();
            PageManager.initialize();
            FavoritesManager.initialize();
            setOmnitureSearchParams(PropertyManager.getActiveProperties());
            FilterManager.initialize({
                container:yuiDom.get("filterGroups"),
                properties:PropertyManager.getActiveProperties()

            });
            FilterManager.filterEvent.subscribe(function(criteria){
                PropertyManager.filter(criteria);
            });

            // Move the below up as one of the above causes tracking failure
            // setOmnitureSearchParams(PropertyManager.getActiveProperties());
        },
        PropertyManager:PropertyManager,
        FilterManager:FilterManager,
        MapManager:MapManager,
        PageManager:PageManager,
        CountManager:CountManager,
        FavoritesManager:FavoritesManager
        // intentially leaving out MessageManager -
        // these items may move to standardConfig.js and thus should not be part of the public interface as it may change
        // MessageManager:MessageManager
    };

    // make API available to public                    
    SW.widget.SearchResults = SearchResults;

    // initialize everything on page load
    yuiEvent.onDOMReady(SearchResults.initialize);
})();