gzo.MarkerService = function(iconFactory)
{
/*
 * Map Marker service 
 */
    var me = this;
    this.iconFactory = iconFactory;

    /* avoid browser caching of results */
    this.skipCache = false;

    /* marker service */
    this.serviceUrl = '/map/boxmarkers/?hotels';

    /* hotel summaries service */
    this.infoUrl = '/map/markerinfo';

    this.currentBoxes = {}; /* list of 9 surrounding boxes */
    this.addedBoxes = {};

    this.clearMarkers = function() {
        this.addedBoxes = [];
    };

    /* 
     * @param array of BoxRequest
     * @param function(Marker) Called for every marker retrieved
     */
    this.getMarkers = function(boxRequests,markerCb)
    {
        this.currentBoxes = {};

        /* function to generate callback closure for each boxKey */
        var getMarkerCallback = function(boxKey){
            return function(resp,status){markerCb(me.handleMarkerResponse(boxKey,resp));};
        };

        for(var i = 0; i < boxRequests.length; i++) {
            var rq = boxRequests[i];
            /* this is one of the current nine */
            this.currentBoxes[rq.key] = true;

            if(this.addedBoxes[rq.key]) {
                continue;
            }
           
            /* if don't want browser cache add a timestamp */ 
            if (this.skipCache){rq.rq.ts = +new Date();}

            jQuery.getJSON(this.serviceUrl,rq.rq,getMarkerCallback(rq.key));
        }
    };

    this.handleMarkerResponse = function(BoxKey,Locations)
    {
        this.addedBoxes[BoxKey] = [];

        if(!Locations) { return; }

        for(i = 0; i < Locations.length; i++) {
            var LocOb = this.LocationOb(Locations[i],this.iconFactory);
            this.addedBoxes[BoxKey].push(LocOb.getMarker());
        } 
        return this.addedBoxes[BoxKey];
    };

    /* translate JSON from service into Location Object */
    this.LocationOb = function(Loc,IconFactory)
    {
        switch(Loc[0]) {
            case 'hotel':
                return new this.HotelLocation(Loc,IconFactory,this.infoUrl);
            case 'cluster':
                return new this.ClusterLocation(Loc,IconFactory);
            default:
                console.debug('unknown location',Loc);
                /* nothing */
        }
    };


    /* Location object for clusters */
    this.ClusterLocation = function(Loc,IconFactory)
    {
        var me = this;
        this.Loc = Loc;
        this.type = Loc[0];
        this.id = Loc[1];
        this.latitude = Loc[2];
        this.longitude = Loc[3];
        this.nMarkers = Loc[4];
        this.swne = Loc[5];
        this.title = this.nMarkers +' hotels - click to zoom in';
        this.icon =  iconFactory.CLUSTER;
        this.handleClick = function(gzo_marker_loader){ gzo_marker_loader.fitToSwne(me.swne); };
        this.highlight =  false;
        this.highlightOn = function(){};
        this.highlightOff = function(){}; 
        this.getMarker = function()
        { 
            this.marker = new google.maps.Marker(
                new google.maps.LatLng(this.latitude,this.longitude),
                {icon:IconFactory.get(this.icon),title:this.title}
            );
            this.marker.gzo_location_ob = this;
            return this.marker;
        };
    };


    /* Location object for hotels */
    this.HotelLocation = function(Loc,IconFactory,InfoUrl)
    {
        var me = this;
        this.Loc = Loc;
        this.type = Loc[0];
        this.id = Loc[1];
        this.latitude = Loc[2];
        this.longitude = Loc[3];
        this.name = Loc[4];
        this.stars = Loc[5];
        this.region = Loc[6];
        this.title =  this.name + ' - click for more information';
        this.icon =  iconFactory.HOTEL;
        this.isHighlit =  false;
        this.getMarker = function()
        { 
            this.marker = new google.maps.Marker(
                new google.maps.LatLng(this.latitude,this.longitude),
                {icon:IconFactory.get(this.icon),title:this.title}
            );
            this.marker.gzo_location_ob = this;
            return this.marker;
        };
        this.handleClick = function(gzo_marker_loader)
        {
            gzo_marker_loader.setSelectedMarkerId(this.id);
            console.debug('me is',me); 
            $.get(
                InfoUrl,
                {type:this.type,id:this.id},
                function(data) {gzo_marker_loader.changeSummary(data,me);}
            );
            return this;
        };

        this.highlightOn = function() { 
            this.isHighlit = true; 
            this.marker.setImage(iconFactory.SELECTED); 
        };

        this.highlightOff = function() { 
            this.isHighlit = false; 
            this.marker.setImage(this.icon); 
        };
        
        this.toggleHighlight = function(){
            if(this.isHighlit){
                this.highlightOff();
            }else{
                this.highlightOn();
            }
        };
    };

    /* add a help section to the jQuery target, using callback for postfix resizes etc */
    this.addKey = function(jqTarget,callback)
    {
        jqTarget
            .html('<div class="hotel marker"><strong>Hotel markers</strong> - click on these to see more information about the hotel.</div><div class="cluster marker"><strong>Cluster markers</strong> represent several hotels in the same area. Click on the markers to zoom into the individual hotels.</div>')
            .children('.marker.hotel')
                .css({backgroundImage: 'url('+this.iconFactory.HOTEL+')'}).end()
            .children('.marker.cluster')
                .css({backgroundImage: 'url('+this.iconFactory.CLUSTER+')'}).end()
            .append(
                $('<a href="javascript:;">Hide help</a>')
                    .css({padding:'10px 0',outline:'0'})
                    .toggle(
                        function() { $(this).text('Show help').siblings().hide(); callback();},
                        function() { $(this).text('Hide help').siblings().show(); callback();}
                    )
            );
    };
};

