var Place = JClass.extend({
    name: '',
    lat: 0,
    lng: 0,
    url: '',

    init: function(params) {
        $.extend(this, params);
    }
});

/* create it ON 'document.ready' */
var PlacesMap = JClass.extend({
    init: function(params) {
        var defaults = {
            center_lat: -10,
            center_lng: 0,
            google_map_id: "map_canvas",
			ut_icon: false,
			ignore_if_one: false
        };

        this.params = $.extend({}, defaults, params || {});

        if (!GBrowserIsCompatible()) {
            alert('Your browser is not compatible with Google Maps');
            return null;
        }

        this._initBaseIcon();
        this.configure();

        $(window).unload(function() { 
            GUnload()
        });
    },

    setZoom: function(level) {
        this.map.setZoom(level);
    },
    
    setMaxZoom: function() {
        this.map.setZoom(this.map.getCurrentMapType().getMaximumResolution() - 1);
    },

    //set the zoom of the map using the bounds
    setZoomFromBounds: function(sw_lat, sw_lng, ne_lat, ne_lng) {
        var level = this.map.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(sw_lat, sw_lng), new GLatLng(ne_lat, ne_lng)));
        this.setZoom(level);
    },

    //create a Place object by a JSON object
    populateByJSONObj: function(obj) {
        if (obj.lat != 0 || obj.lng != 0) {
            var maker = this.addPlace(obj);
        }
    },

    setCenter: function(lat, lng) {
        this.map.setCenter(new GLatLng(lat, lng));
    },

    //populate the map by an ajax request. 
    //Url is optional, if you don't specify it, the current url will be used.
    populateByAjax: function(url) {
        var context = this;
        
        if (url == null) {
            url = (window.location.search.length > 0) ? window.location.search : window.location.pathname;
        }

		url += (url.indexOf("?") == -1) ? "?" : "&";
		url += "ajax=true";

        $.get(url, function(data){
            var json_obj = eval('(' + data + ')');
            if (json_obj.result.length > 0 && !(context.params['ignore_if_one'] && context.ignore_if_one_val(json_obj.result))) {
                for (i in json_obj.result) {
                    context.populateByJSONObj(json_obj.result[i]);
                }
            }

            context.post_load(json_obj);
        });
    },

	ignore_if_one_val: function(objs) {
		return objs.length == 1;
	},

    post_load: function(json_obj) {},

/* use this for the rounded icon */
    _initBasicIcon: function() {
        var bicon = new GIcon(G_DEFAULT_ICON);
        bicon.shadow = "/site_media/site_images/icons/google_pin_rounded_shadow.png";
        bicon.iconSize = new GSize(32, 37);
        bicon.shadowSize = new GSize(42, 34);
        bicon.iconAnchor = new GPoint(9, 34);
        bicon.infoWindowAnchor = new GPoint(15, 2);
        bicon.image = "/site_media/site_images/icons/google_pin_rounded.png";

        return bicon
    },

    //can be used to create a basic icon and customize it
    _initUTBasicIcon: function() {
        var bicon = new GIcon(G_DEFAULT_ICON);
        bicon.shadow = "/site_media/site_images/icons/google_pin_shadow.png";
        bicon.iconSize = new GSize(25, 37);
        bicon.shadowSize = new GSize(42, 34);
        bicon.iconAnchor = new GPoint(9, 34);
        bicon.infoWindowAnchor = new GPoint(15, 2);
        bicon.image = "/site_media/site_images/icons/google_pin.png";

        return bicon
    },

    _initBaseIcon: function() {
		if (this.params['ut_icon']) {
        	this.baseIcon = this._initUTBasicIcon()
		} else {
			this.baseIcon = this._initBasicIcon()
		}
    },

    //creates the google map, set center, zoom and UI
    configure: function() {
        this.map = new GMap2(document.getElementById(this.params['google_map_id']));
        this.map.setCenter(new GLatLng(this.params['center_lat'], this.params['center_lng']), 1);
        this.map.setUIToDefault();
		this.map.disableScrollWheelZoom();

    },

    //used by _createMarker, you can override it to return another icon for a specific place
    _getGIcon: function(place) {
        return this.baseIcon;
    },
    
    //used by _createMarker, you can override it to return anothor InfoWindowHtml
    _getInfoWindowHtml: function(place, marker) {
        return '<h3>' + place.name + '</h3><p><a href="' + place.url + '">Explore this location</a></p>'
    },

    _postAddPlace: function(place, marker) {
    },

    //creates a marker from a point and a generic place object
    _createMarker: function(point, place) {
        var icon = new GIcon(this._getGIcon(place));
        var marker = new GMarker(point, { icon:icon });

        var context = this;
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(context._getInfoWindowHtml(place, marker));
        });

        return marker;
    },

    //creates an object of type 'clazz' and creates a marker
    _addPlace: function(clazz, params) {
        var place = new clazz(params);
        var marker = this._createMarker(new GLatLng(place.lat, place.lng), place);
        this.map.addOverlay(marker);

        this._postAddPlace(place, marker);

        return marker;
    },

    //creates an object of type Place
    addPlace: function(params) {
        return this._addPlace(Place, params);
    }
});