/**
    This utility is intended to be used with FlterGroupUtility (and related classes), which uses
    dctm config's stored in /html/Site/Lists/Configuration/Search/

    Currently used by new Search Results and new Directory pages
*/

(function(){
    var yuiDom = YAHOO.util.Dom,
        yuiEvent = YAHOO.util.Event,
        customEvent = YAHOO.util.CustomEvent,
        yuiLang = YAHOO.lang,
        Url = SW.tools.Url,
        widget = SW.widget;

    var FilterManager = (function() {
        // private
        var initialized = false;
        var filters = [];
        var properties = [];
        var allProperties = [];
        var container = null;
        var activeFilters = [];
        var FILTER_TYPE_TO_FIELD = {
            amenity:"amenities",
            brand:"brandCode",
            category:"category"
        };
        // lookup lists
        var FILTERS_BY_TYPE = {
            amenity:[],
            brand:[],
            category:[]
        };

        function setProperties(props){
            // create lightwieght representation of properties
            function processProperty(prop){
                allProperties.push({
                    propertyId:prop.propertyId,
                    amenities:prop.amenities,
                    brandCode:prop.brandCode,
                    category:prop.category
                })
            }
            props.forEach(processProperty);
            properties = Array.Copy(allProperties);
        }

        function applyActiveFilters() {
            var criteria = [];
            activeFilters.forEach(function(filter) {
                var op = "equals";
                if (filter.type == "amenity") {
                    op = "contains";
                }
                allProperties.setFilter(filter.filterField,filter.criteria,op);
                criteria.push([filter.filterField,filter.criteria,op]);
            });
            properties = allProperties.objectFilter();
            self.filterEvent.fire(criteria);
        }
        function toggleFilter(e) {
            // filter states: active, selected, inactive
            var target = yuiEvent.getTarget(e);
            var config = target.filterConfig;
            yuiEvent.preventDefault(e);

            if (yuiDom.hasClass(config.anchor, "inactiveFilter")) {
                return;
            }
            if (yuiDom.hasClass(config.anchor, "activeFilter")) {
                self.removeFilter(config);
            } else {
                self.applyFilter(config);
            }
        }

        function resetCounts() {
            filters.forEach(function(filter) {
                filter.count = 0;
            });
        }
        function updateCounts() {
            properties.forEach(function(property) {
                filters.forEach(function(filter) {
                    var val = property[filter.filterField];
                    if (!yuiLang.isArray(val)) {
                        val = [val];
                    }
                    for (var i = 0; i < filter.criteria.length; i++) {
                        if (val.indexOf(filter.criteria[i]) > -1) {
                            filter.count++;
                            return;
                        }
                    }
                });
            });
        }
        function updateClassNames() {
            filters.forEach(function(filter) {
                filter.countElement.innerHTML = filter.count;
                filter.anchor.className = "filter";
                if (filter.count == 0) {
                    yuiDom.addClass(filter.anchor, "inactiveFilter");
                }
            });
            activeFilters.forEach(function(filter) {
                yuiDom.addClass(filter.anchor, "activeFilter");
            });
        }

        function applyFiltersAndDisplay() {
            applyActiveFilters();
            resetCounts();
            updateCounts();
            updateClassNames();
        }

        // public
        var self = {
            initialize:function(config) {
                if (initialized) {
                    return;
                }
                initialized = true;
                container = config.container;
                setProperties(config.properties);
                // parse filters
                var lists = Array.Copy(container.getElementsByTagName("ul"));
                lists.forEach(function(list) {
                    var anchors = yuiDom.getElementsByClassName("filter", "a", list);
                    anchors.forEach(function(anchor) {
                        var filterType = Url.getParameter(anchor.href, "filterType");
                        var countElement = anchor.getElementsByTagName("span")[0];
                        var value = Url.getParameter(anchor.href, "filterCriteria").split(",");
                        if (filterType == "category") {
                            // category will always be single value (might be empty) and needs to be an int (NaN is ok)
                            value[0] = parseInt(value[0], 10);
                        }
                        var config = {
                            anchor:anchor,
                            countElement:countElement,
                            criteria:value,
                            type:filterType,
                            filterField:FILTER_TYPE_TO_FIELD[filterType],
                            count:0
                        };
                        anchor.filterConfig = config;
                        countElement.filterConfig = config;
                        filters.push(config);
                        FILTERS_BY_TYPE[filterType].push(config);
                        yuiEvent.addListener(anchor, "click", toggleFilter);
                    });
                });
            },
            // updateDisplay is generally called just after initialize when no filters are set
            updateDisplay:function() {
                resetCounts();
                updateCounts();
                updateClassNames();
            },
            // applyFilter and removeFilter are called when an individual filter is clicked
            // these could be internal methods, but exposing in case they need to be called programatically
            applyFilter:function(config) {
                activeFilters.push(config);
                applyFiltersAndDisplay();
            },
            removeFilter:function(config) {
                activeFilters.remove(config);
                applyFiltersAndDisplay();
            },
            removeAllFilters:function() {
                activeFilters.length = 0;
                applyFiltersAndDisplay();
            },
            getActiveCriteria:function(){
                var criteria = [];
                activeFilters.forEach(function(filter) {
                    var op = "equals";
                    if (filter.type == "amenity") {
                        op = "contains";
                    }
                    criteria.push([filter.filterField,filter.criteria,op]);
                });
                return criteria;
            },
            // applyFilterManual should only be called on load of page
            // use when reading filters from current url to pre-filter items
            setFilter:function(type, criteria){
                var i,j,k;
                var thisConfig,configCriteria;
                var filterList = FILTERS_BY_TYPE[type];
                configLoop:for (i = 0; i < filterList.length; i++) {
                    thisConfig = filterList[i];
                    for (j = 0; j < thisConfig.criteria.length; j++) {
                        configCriteria = thisConfig.criteria[j];
                        for (k = 0; k < criteria.length; k++) {
                            if (configCriteria == criteria[k]) {
                                activeFilters.push(thisConfig);
                                continue configLoop;
                            }
                        }
                    }
                }
            },
            applyFiltersAndDisplay:function(){
                applyFiltersAndDisplay();
            },
            applyFilterManual:function(type, criteria) {
                setFilter(type, criteria);
                applyFiltersAndDisplay();
            },

            // custom events
            beforeFilterEvent:new customEvent("beforeFilterEvent"),
            filterEvent:new customEvent("filterEvent",null,false,YAHOO.util.CustomEvent.FLAT)

            // beforeUpdateDisplay, updateDisplayEvent
            // "before" events - can the return value be checked?
        };
        return self;
    })();


    widget.FilterManager = FilterManager;
})();

/*
To Do:
remove dependency on PropertyManager
setProperties via events

think filtering of properties needs to happen in FilterManager...
 filterEvent will based same criteria used to filter
 consider only copying required fields instead of entire array (ie amenities, propertyId, brandCode, category)

*/

/*
(function(){
    // Search Results setup
    var yuiDom = YAHOO.util.Dom,
        yuiEvent = YAHOO.util.Event,
        customEvent = YAHOO.util.CustomEvent,
        yuiLang = YAHOO.lang,
        FilterManager = SW.widget.FilterManager;
    
    yuiEvent.onDOMReady(function(){
        FilterManager.initialize({
            container:yuiDom.get("filterGroups"),
            properties:PropertyManager.getActiveProperties()

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