// Setup indexOf for browsers that don't have it.

if (!Array.prototype.indexOf)
{
    Array.prototype.indexOf = function(elt /*, from*/) {
        var len = this.length;
        var from = Number(arguments[1]) || 0;
    
        from = (from < 0) ? Math.ceil(from) : Math.floor(from);
        if (from < 0) from += len;
    
        for (; from < len; from++) {
            if (from in this && this[from] === elt)
                return from;
        }
        return -1;
    };
}

var Booking = Booking || {};

Booking.facet = {
    congressData: null,
    searchParameters: {},
    orderBy: null,
    
    pricesMin: 0,
    pricesMax: 0,
    distanceMin: 0,
    distanceMax: 0,
    starsMin: -1,
    starsMax: 0,
    
    packetsName: "Wellness Special",
    packetsCount: 0,
    
    map: null,
    mapBounds: null,
    geo: null,
    marker: null,

    parseSearchResults: function()
    {
        // Parse search result JSON data.
        
        $(".search-item").each(function() {
            var elt = $(this);
            var json = elt.find(".json-data");
            if (json.length == 1 && !this.searchData)
                this.searchData = eval("("+json.text()+")");
        });
        Booking.facet.congressData = eval("("+$("#congress-data").text()+")");

        // Setup facets.
        
        Booking.facet.setupStarsFacet("stars", function(facetData, v) {
            return facetData[0] <= v && facetData[1] >= v;
        });
        Booking.facet.setupAccomodationFacet("accomodation", function(facetData, v) {
            return facetData == v.split("|")[0];
        });
        Booking.facet.setupPricesFacet("prices", function(facetData, v) {
            return facetData[0] <= v[0] && facetData[1] >= v[v.length-1];
        });
        Booking.facet.setupDistanceFacet("distance", function(facetData, v) {
            return (facetData[0] <= v && facetData[1] >= v) || facetData == Booking.facet.distanceMax;
        });
        
        $("#search-order div button").click(Booking.facet.sort);

        // Setup Google Maps and execute first filter.

        Booking.facet.setupGMap();
        Booking.facet.filter();   
    },

    setupGMap: function()
    {
        var count = 100;

        if (!GBrowserIsCompatible()) return;
        
        var items = $(".search-item");
        
        var congress = Booking.facet.congressData;
        var map = Booking.facet.map = new GMap2($("#map-box").get(0));
        var geo = Booking.facet.geo = new GClientGeocoder();
        var bounds = Booking.facet.mapBounds = new GLatLngBounds();
        
        Booking.facet.focusIcon = MapIconMaker.createMarkerIcon({width: 32, height: 32, primaryColor: Booking.page.gmapFocusIconColor});
        Booking.facet.mainIcon  = MapIconMaker.createMarkerIcon({width: 24, height: 24, primaryColor: Booking.page.gmapMainIconColor});

        // The function that we'll use to do all the map rendering after
        // using the geo-reference APIto obtain hotel positions.

        function createMarker(item) {
            var marker = item.searchData.geomarker = new GMarker(item.searchData.geopoint,
                { title: item.searchData.name, icon: Booking.facet.mainIcon });
            GEvent.addListener(marker, "click", function() {
                $("#results-container").scrollTo(item, 800);
                Booking.facet.focusGMapHotel(item);
            });
            return marker;
        }
        
        function renderMap() {
            map.setCenter(bounds.getCenter());
            map.setZoom(map.getBoundsZoomLevel(bounds));
            map.enableScrollWheelZoom();
            map.addControl(new GSmallMapControl());
            //map.addControl(new GMapTypeControl());

            for (var i=0 ; i < items.length ; i++) {
                var item = items.get(i);
                if(!item) continue;
                if (item.searchData.geopoint)
                    map.addOverlay(createMarker(item));
            }

            // Setup event position and range.
            if (congress.geopoint) {
                var title = congress.event_title || congress.event_name;
                var marker = new GMarker(congress.geopoint, { icon: Booking.facet.createCongressGIcon(), title: title } );
                map.addOverlay(marker);
                marker.bindInfoWindowHtml("<strong>"+title+"</strong><br /><em>"+congress.name+"</em><br />"+congress.address2);                    
            }
        }
        
        // Make sure to not send too much request too fast.
        
        function sendEventGeoRequest() {
            function doSet(point) {
                if (point) {
                    congress.geopoint = point;
                    bounds.extend(point);
                }
                renderMap();
            }

            if (!congress.lat || !congress.lng)
                geo.getLatLng(congress.address1, doSet);
            else
                doSet(new GLatLng(congress.lat, congress.lng));
        }

        function sendGeoRequest(items) {
            var item = items.pop();
            if(!item) return;

            function doSet(point) {
                if (point) {
                    item.searchData.geopoint = point;
                    bounds.extend(point);
                }
                if (items.length > 0 && --count > 0)
                    sendGeoRequest(items);
                else
                    sendEventGeoRequest();
            }
            
            if (!item.searchData.lat || !item.searchData.lng)
                geo.getLatLng(item.searchData.address1, doSet);
            else
                doSet(new GLatLng(item.searchData.lat, item.searchData.lng));
        }
        
        sendGeoRequest($.makeArray(items));
    },

    redrawGMap: function(bounds)
    {
        if (Booking.facet.map && Booking.facet.map.isLoaded()) {
            if (bounds)
                Booking.facet.mapBounds = bounds;
            Booking.facet.map.checkResize();
            Booking.facet.map.setCenter(Booking.facet.mapBounds.getCenter());
            Booking.facet.map.setZoom(Booking.facet.map.getBoundsZoomLevel(Booking.facet.mapBounds));
        }
        else {
            setTimeout("Booking.facet.redrawGMap()", 100);
        }
    },

    focusGMapHotel: function(item)
    {
        function formatPopup(data) {
            return "<strong>"+data.searchData.name+"</strong><br />"+data.searchData.address2;
        }
        
        if (!item.searchData.geomarker) return;

        if (Booking.facet.marker != null) {
            Booking.facet.map.removeOverlay(Booking.facet.marker[0]);
            Booking.facet.map.addOverlay(Booking.facet.marker[1]);
        }
        var marker = new GMarker(item.searchData.geopoint, { title: item.searchData.name, icon: Booking.facet.focusIcon });
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(formatPopup(item));
        });
        Booking.facet.map.removeOverlay(item.searchData.geomarker);
        Booking.facet.map.addOverlay(marker);
        Booking.facet.marker = [marker, item.searchData.geomarker];
        Booking.facet.map.panTo(item.searchData.geopoint);
        
        marker.openInfoWindowHtml(formatPopup(item));
    },

    createCongressGIcon: function() {
        var icon = new GIcon(G_DEFAULT_ICON);
        icon.image = "/ui/icons/gcongress38x34.png";
        icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
        icon.iconSize = new GSize(38, 34);
        icon.shadowSize = new GSize(37, 34);
        icon.iconAnchor = new GPoint(9, 34);
        icon.infoWindowAnchor = new GPoint(18, 2);

        var pathSplitted = parseUri(window.location).path.split('/');
        if (pathSplitted[pathSplitted.length-1] == "STRAMILANO2009") {
            icon.image = "/skins/STRAMILANO2009/ui/gcongress.png";
            icon.iconSize = new GSize(24, 15);
        }
        return icon;
    },
    
    setupCheckBoxFacet: function(facet, cmp)
    {
        function check(evt) {
            var target = $(evt.target);
            if (!target.is("input")) return;
            
            if (target.attr("id") == facet+"-all" && target.attr('checked')) {
                $("#facet-"+facet).find("input").each(function() {
                    var e = $(this);
                    if (e.attr("id") != facet+"-all") e.removeAttr('checked');
                });
            }
            else if (target.attr('checked')) {
                $("#"+facet+"-all").removeAttr('checked');      
            }
            
            var data = [], count = 0;
            $("#facet-"+facet).find("input").each(function() {
                var e = $(this);
                if (e.attr('checked') && e.attr("id") != facet+"-all") {
                    data.push(e.val());
                    count += 1;
                }
            });
            if (count == 0)
                $("#"+facet+"-all").attr('checked', 1);
                
            if (data.length > 0)
                Booking.facet.searchParameters[facet] = function(v) { return cmp(data, v); }
            else
                delete Booking.facet.searchParameters[facet];
            
            Booking.facet.filter();
        }
        
        $("#facet-"+facet).find("input").each(function() {
            var e = $(this);
            var data = [e.val()];
            var matches = Booking.facet.applyFacets(facet, function(v) { return cmp(data, v); });
            if (matches.length > 0 || e.attr("id") == facet+"-all") {
                e.bind('click', check);
            }
            else {
                e.attr("disabled", true);
                $(this).parent().addClass("disabled");
            }
        });
    },

    setupPricesFacet: function(facet, cmp)
    {
        function format(min, max) {
            $("#facet-"+facet+"-display").text("€"+min+" - €"+max);
        }
        
        function slide(evt, ui) {
            format($("#facet-"+facet+"-slider").slider('value', 0), $("#facet-"+facet+"-slider").slider('value', 1));
        }
        
        function change(evt, ui) {
            var data = [$("#facet-"+facet+"-slider").slider('value', 0), $("#facet-"+facet+"-slider").slider('value', 1)];
            Booking.facet.searchParameters[facet] = function(v) { return cmp(data, v); }
            Booking.facet.filter();
        }

        $("#results-box").children().each(function(index) {
            var data = this.searchData;
            if (!data) return;

            if (data.prices[0] < Booking.facet.pricesMin || Booking.facet.pricesMin == 0)
                Booking.facet.pricesMin = data.prices[0];
            if (data.prices[data.prices.length-1] > Booking.facet.pricesMax)
                Booking.facet.pricesMax = data.prices[data.prices.length-1];
        })
        format(Booking.facet.pricesMin, Booking.facet.pricesMax);
        
        $("#facet-"+facet+"-slider").slider({
            range: true,
            min: Booking.facet.pricesMin,
            max: Booking.facet.pricesMax,
            slide: slide,
            change: change
        });
    },
    
    setupStarsFacet: function(facet, cmp)
    {
        function format(min, max) {
            if (min == 0) min = "NA";
            $("#facet-"+facet+"-display").text(min+" - "+max);
        }
        
        function slide(evt, ui) {
            format($("#facet-"+facet+"-slider").slider('value', 0), $("#facet-"+facet+"-slider").slider('value', 1));
        }
        
        function change(evt, ui) {
            var data = [$("#facet-"+facet+"-slider").slider('value', 0), $("#facet-"+facet+"-slider").slider('value', 1)];
            Booking.facet.searchParameters[facet] = function(v) { return cmp(data, v); }
            Booking.facet.filter();
        }

        $("#results-box").children().each(function(index) {
            var data = this.searchData;
            if (!data) return;

            if (data.stars < Booking.facet.starsMin || Booking.facet.starsMin == -1)
                Booking.facet.starsMin = data.stars;
            if (data.stars > Booking.facet.starsMax)
                Booking.facet.starsMax = data.stars;
        })
        format(Booking.facet.starsMin, Booking.facet.starsMax);
        
        $("#facet-"+facet+"-slider").slider({
            range: true,
            min: Booking.facet.starsMin,
            max: Booking.facet.starsMax,
            slide: slide,
            change: change
        });
    },    

    setupAccomodationFacet: function(facet, cmp)
    {
        var select = $("#facet-"+facet+"-select");

        var options = [];
        $("#results-box").children().each(function(index) {
            var data = this.searchData;
            if (!data) return;

            if (options.indexOf(data.accomodation) == -1)
                options.push(data.accomodation);
        })
        options.sort();
        for (var i=0 ; i < options.length ; i++) {
            var parts = options[i].split("|");
            if (parts[0] == Booking.facet.packetsName)
                Booking.facet.packetsCount += 1;
            $("<option/>").text(parts[1]).attr("value", parts[0]).appendTo(select);
        }
        
        select.change(function(evt) {
            Booking.facet.triggerAccomodationFacet("accomodation", $(this).val());
        });
        
        Booking.facet.triggerAccomodationFacet = function(facet, data)
        {
            if (data)
                Booking.facet.searchParameters[facet] = function(v) { return cmp(data, v); }
            else
                delete Booking.facet.searchParameters[facet];
            Booking.facet.filter();    
        };
    },

    setupDistanceFacet: function(facet, cmp)
    {
        function format(min, max) {
            if (max == Booking.facet.distanceMax)
                max = ">"+max;
            $("#facet-"+facet+"-display").text(min+"km - "+max+"km");
        }
        
        function slide(evt, ui) {
            format($("#facet-"+facet+"-slider").slider('value', 0)/100, $("#facet-"+facet+"-slider").slider('value', 1)/100);
        }
        
        function change(evt, ui) {
            var data = [$("#facet-"+facet+"-slider").slider('value', 0)/100, $("#facet-"+facet+"-slider").slider('value', 1)/100];
            Booking.facet.searchParameters[facet] = function(v) { return cmp(data, v); }
            Booking.facet.filter();
        }

        $("#results-box").children().each(function(index) {
            var data = this.searchData;
            if (!data) return;

            if (data.distance < Booking.facet.distanceMin || Booking.facet.distanceMin == 0)
                Booking.facet.distanceMin = data.distance;
            if (data.distance > Booking.facet.distanceMax)
                Booking.facet.distanceMax = data.distance;
        })
        if (Booking.facet.distanceMax > 25)
            Booking.facet.distanceMax = 25;
        format(Booking.facet.distanceMin, Booking.facet.distanceMax);
        
        $("#facet-"+facet+"-slider").slider({
            range: true,
            min: Booking.facet.distanceMin*100,
            max: Booking.facet.distanceMax*100,
            slide: slide,
            change: change
        });
    },

    sort: function(evt)
    {
        Booking.facet.orderBy = $(evt.target).attr("id").replace("button-order-by-", "");
        $("#search-order button").removeClass("selected");
        $(evt.target).addClass("selected");
        Booking.facet.filter();
    },
    
    filter: function()
    {
        
        $("#results-box").children().filter(function(index) { return this.searchData; }).addClass("hidden");
        
        var array = $.makeArray(Booking.facet.applyFacets());
        array.sort(function(a,b) {
            if (Booking.facet.orderBy == "name")
                return a.searchData.name.localeCompare(b.searchData.name);
            else if (Booking.facet.orderBy == "stars")
                return a.searchData.stars - b.searchData.stars;
            else if (Booking.facet.orderBy == "distance")
                return a.searchData.distance - b.searchData.distance;
            else
                return a.searchData.prices[0] - b.searchData.prices[0];
        });
        $(array).removeClass("hidden").appendTo("#results-box");
        
        var count = 0;
        $.each(array, function(i, elt) { count += elt.searchData.prices.length; });
        $("#search-results-count").text(count+" ");
        $("#search-results-no-rooms").hide();
        if (count == 0) {
            $("#search-order").hide();
            if (array.length > 0) {
                $("#search-results-no-rooms").show();
                $("#search-results-no-rooms button").one('click', function() { $("#search-form").get(0).submit(); });
            }
        }
        else {
            $("#search-order").show();
            $("#search-results-no-rooms").hide();
        }

        // Show active markers and calculate new map bounds.
        
        var bounds = new GLatLngBounds();
        
        $("#results-box").children().filter(function(index) { return this.searchData; }).each(function(i, elt) {
            if (!elt.searchData.geomarker) return;
                        
            if ($(elt).hasClass("hidden")) {
                elt.searchData.geomarker.hide();
            }
            else {
                elt.searchData.geomarker.show();
                bounds.extend(elt.searchData.geopoint);
            }
        });
        
        if (Booking.facet.congressData.geopoint)
            bounds.extend(Booking.facet.congressData.geopoint);
        
        Booking.facet.redrawGMap(bounds);
        //Booking.page.setupScrollPane();
    },
    
    applyFacets: function(facet, cmp, excluded)
    {
        var container = $("#results-box");
        var sp = Booking.facet.searchParameters;
        var res = !excluded;
        
        return container.children().filter(function(index) {
            var e = $(this);
            if (!this.searchData) return false;
            
            var data = this.searchData;
            if (facet && cmp) {
                if (cmp(data[facet]) == false)
                    return !res;
            }
            else {
                for (var k in sp) {
                    if (sp[k](data[k]) == false) 
                        return !res;
                }
            }
            
            return res;
        });      
    }
};
