
DB = {};

DB.methodCaller = function(obj, methodName) {
    return function() {
        return obj[methodName].apply(obj, arguments);
    }
}

//
// MapControl
//

DB.MapControl = function (elName) {
    this.div = document.getElementById(elName);
    this.places = [];

    this.baseIcon = new GIcon();
    this.baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
    this.baseIcon.iconSize = new GSize(20, 34);
    this.baseIcon.shadowSize = new GSize(37, 34);
    this.baseIcon.iconAnchor = new GPoint(9, 34);
    this.baseIcon.infoWindowAnchor = new GPoint(9, 2);
    this.baseIcon.infoShadowAnchor = new GPoint(18, 25);
    
    this.geocoder = new GClientGeocoder();
    
    this.map = new GMap2(this.div);
    this.map.addControl( new GSmallMapControl() );
}

DB.MapControl.prototype.add = function (name, address, label) {
    this.places.push({name:name, address:address, label:label});
}

DB.MapControl.prototype.renderOne = function (index) {
    if (GBrowserIsCompatible()) {
        this.mode = 'one';
        this.placeIndex = index;
        this.geocoderResponses = 0;
        this.expectedGeocodeResponses = 1;
        this.showAddress(this.places[index]);
    }
}

DB.MapControl.prototype.renderAll = function () {
    if (GBrowserIsCompatible()) {
        this.mode = 'many';
        this.geocoderResponses = 0;
        this.expectedGeocodeResponses = this.places.length;
        for (var i = 0; i < this.places.length; i++) {
            this.showAddress(this.places[i]);
        }
    }
}


DB.MapControl.prototype.isInlineLabel = function (label) {
    return (label.url == undefined) ? false : true;
}

DB.MapControl.prototype.getIconUrl = function (label) {
    if (this.isInlineLabel(label))
        return label.url;
    else if (label == "pushpin")
        return "http://maps.google.com/mapfiles/ms/micons/blue-pushpin.png";
    else
        return "/static/images/mapping/" + label + ".gif";
}

DB.MapControl.prototype.getIconShadowUrl = function (label) {
    if (this.isInlineLabel(label))
        return label.shadowUrl;
    else if (label == "pushpin")
        return "http://maps.google.com/mapfiles/ms/micons/pushpin_shadow.png";
    else
        return undefined;
}

DB.MapControl.prototype.getIconSize = function (label) {
    if (this.isInlineLabel(label))
        return label.size;
    else if (label == "pushpin")
        return new GSize(32,32);
    else
        return undefined;
}

DB.MapControl.prototype.getIconShadowSize = function (label) {
    if (this.isInlineLabel(label))
        return label.shadowSize;
    else if (label == "pushpin")
        return new GSize(59,32);
    else
        return new GSize(59,32);
}



// internal

DB.MapControl.prototype.computeListingsBounds = function () {
    var bounds = new GLatLngBounds();
    for (var i = 0; i < this.places.length; i++) {
        var point = this.places[i].point;
        if (point)
            bounds.extend(point);
    }
    return bounds;
}

DB.MapControl.prototype.createMarker = function (point, label) {
    var icon = new GIcon(this.baseIcon);
    icon.image = this.getIconUrl(label);
    icon.shadow = this.getIconShadowUrl(label);
    icon.iconSize = this.getIconSize(label);
    icon.shadowSize = this.getIconShadowSize(label);
    var marker = new GMarker(point, icon);
    return marker;
}

DB.MapControl.prototype.showAddress = function (place) {
    var me = this;
    this.geocoder.getLatLng(
        place.address,
        function(point) {
            if (point) {
                place.point = point;
                if (me.setCenterCalled == undefined) {
                    me.map.setCenter(point);
                    me.setCenterCalled = true;
                }
                var marker = me.createMarker(point, place.label);
                me.map.addOverlay(marker);
            }
            if (++me.geocoderResponses == me.expectedGeocodeResponses)
                me.onGeocodeCompleted();
        }
    );
}

DB.MapControl.prototype.onGeocodeCompleted = function () {
    if (this.onRenderCompleted) {
        this.onRenderCompleted();
    }
    else if (this.mode == 'one') {
        var place = this.places[this.placeIndex];
        this.map.setCenter(place.point, 15);
        var marker = new GMarker(place.point);
        this.map.addOverlay(marker);
        marker.openInfoWindowHtml('<strong>' + place.name + '</strong>' + '<br>' + place.address);        
    }
    else {
        var bounds = this.computeListingsBounds();
        var center = bounds.getCenter();
        var zoomLevel = Math.min(15,this.map.getBoundsZoomLevel(bounds));
        this.map.setCenter(center, zoomLevel);        
    }
}
