/*****************************
 Handles places selection through the Google Map.

 Places are loaded with ajax and positioned on the map.
 Selected places are added to list.

 When user clicks on a place:
    1. it is attached/detached with ajax
    2. color is changed accordingly
    3. line added to/removed from attached places list

 Note listLineTemplate structure. It has two mandatory elements:
    1. ".text" element for place name
    2. "a.remove-place" for removal link

 *****************************/
PlacesSelector.prototype = new PlacesMap();
function PlacesSelector(options) {
    PlacesMap.call(this, options);
    this.opts = $.extend({
        list: $("#attached-places"),
        listLineTemplate: $('<li><!--<a class="remove-place" href="#">remove</a>--></li>'),
        canRemove: true,
        selectedStyle: {
            color: "#932459",
            opacity: 0.4
        },
        selectedHlStyle: {
            color: "#932459",
            opacity: 0.4
        },
        deselectedHlStyle: {
            color: "#D02A26",
            opacity: 0.3
        },
        deselectedStyle: {
            color: "white",
            opacity: 0.01
        },
        initGetParameters: {},
        onSelect: function(){},
        onDeselect: function(){}
    }, this.opts);
}

PlacesSelector.prototype.initPlace = function(place) {
    if (place.id in this.places) {
        if (!place.selected && !place.attached) return false;
        place.polygon = this.places[place.id].polygon;
    } else {
        place.polygon = this.createPolygon(place);
    }

    this.places[place.id] = place;
    this.initPolygonSelection(place);
    this.initPlaceHandlers(place);
    return place;
};

PlacesSelector.prototype.initPolygonSelection = function(place) {
    var self = this;

    if (typeof(place.selected) == 'undefined') {
        place.selected = place.attached;
    }

    if (self.opts.canRemove || !place.attached) {
        GEvent.addListener(place.polygon, 'click', function(latlng) {
            self.togglePlace(place.id);
        });
    }

    self.setPlaceStatus(place.id, place.selected);
    if (!place.selected) {
        return;
    }
};

PlacesSelector.prototype.getHighLightStyle = function(place, hover) {
    if (hover) {
        return place.selected ? this.opts.selectedHlStyle : this.opts.deselectedHlStyle;
    } else {
        return place.selected ? this.opts.selectedStyle : this.opts.deselectedStyle;
    }
};


PlacesSelector.prototype.init = function() {
    PlacesMap.prototype.init.apply(this);
    var self = this,
        anchor = document.location.hash,
        sourcesToLoad = 0,
        loadedPlaces = [];

    function locateMap(places) {
        sourcesToLoad--;
        loadedPlaces = loadedPlaces.concat(places);

        if (!sourcesToLoad) {
            var bounds = new GLatLngBounds();
            $.each(loadedPlaces, function() {
                if (!this.polygon) {return};
                for (var i=0; i<this.polygon.getVertexCount(); i++) {
                    bounds.extend(this.polygon.getVertex(i));
                }
            });

            if (!bounds.isEmpty()) {
                self.map.setCenter(bounds.getCenter(), self.map.getBoundsZoomLevel(bounds));
            }
        }
    }

    // do not load attached places if places can be removed and we have places in anchor
    // if we can remove places - then places in anchor should completely alter selection
    // not just be additional selection to already attached places.
    if (!(this.opts.canRemove && anchor)) {
        sourcesToLoad++;
        $.get(self.opts.placesGetURL, self.opts.initGetParameters, function(data){
            locateMap($.map(data.places, function(this_) {
                this_.attached = true;
                var place = self.initPlace(this_);

                if (place) {
                    self.addOverlay(place.id);
                    return place;
                }
                return self.places[this_.id];
            }));
        });
    }

    if (anchor) {
        var attached = anchor.substring(1).split(',');
        sourcesToLoad++;
        $.get(self.opts.placesGetURL, {id: attached, no_campaigns: true}, function(data){
            locateMap($.map(data.places, function(this_) {
                this_.selected = true;
                var place = self.initPlace(this_);

                if (place) {
                    self.addOverlay(place.id);
                    return place;
                }
                return self.places[this_.id];
            }));
        });
    }

    // add places ids to 'create district' link
    // TODO: move somewhere else or provide options for customization
    $("a#district").click(function(){
        var $$ = $(this),
        href = $$.attr("href"),
        places = $.map($("#places-form input[name=places]"), function(input) {
            return $(input).val();
        });

        $$.attr("href", href + "?places=" + places.join(","));
        return true;

    });
};

PlacesSelector.prototype.setPlaceStatus = function(placeID, action) {
    var place = this.places[placeID],
        self = this;
    
    place.selected = action;

    if (place.selected) {
        self.alwaysVisible.push(place.id);
        //self.addOverlay(place.id);
        if (!(place.id in self.visiblePlaces)) {
            self.addOverlay(place.id);
        }
    } else {
        var index = $.inArray(place.id, self.alwaysVisible);
        self.alwaysVisible.splice(index, 1);
    }

    place.polygon.setFillStyle(place.selected ? self.opts.selectedStyle : self.opts.deselectedStyle);
};

PlacesSelector.prototype.togglePlace = function(placeID) {
    var place = this.places[placeID],
        self = this;

    self.setPlaceStatus(placeID, !place.selected);
    place.selected ? self.opts.onSelect(place) : self.opts.onDeselect(place);

    self.tooltip.html(self.getTooltipHtml(place));
};

PlacesSelector.prototype.getTooltipHtml = function(place) {
    var self = this,
        simple = $(PlacesMap.prototype.getTooltipHtml.apply(this, [place]));

    if (place.selected) {
        simple.prepend("<span class='delete'></span>")
    } else {
        simple.prepend("<span class='add'></span>").removeClass('small').append('<span class="meta">' + gettext('Click to select') + '</span>');
        if (simple.hasClass('inline-huge')) {
            simple.removeClass('inline-huge').addClass('huge')
        }
    }
    return simple.wrap('<div>').parent().html();
};

