﻿GoogleMapV3 = function (mapDivId, infoDivId, mapType, defaultZoom, maxZoom, startPoint) {
    this._domMapDiv = document.getElementById(mapDivId);
    if (infoDivId != null && infoDivId.length > 0)
        this._domInfoDiv = document.getElementById(infoDivId);
    this._markers = new Array();
    this._geocoder = null;
    this._bounds = null;
    this._objMap = null;
    this._infoWindow = null;
    this._tempLocation = null;
    this._currentIndex = 0;
    this._iconShadow = null;
    this._icons = new Array();
    this._callback = null;
    this._showCallback = null;
    this._hideCallback = null;
    this._zoomTemp = 0;
    this._startPoint = null;
    if (startPoint)
        this._startPoint = startPoint;

    this._zoom = 12;
    if (defaultZoom && defaultZoom > 0)
        this._zoom = defaultZoom;

    this._maxZoom = 21;
    if (maxZoom && maxZoom > 0)
        this._maxZoom = maxZoom;

    this._mapType = google.maps.MapTypeId.ROADMAP;
    if (mapType)
        this._mapType = mapType;
}

GoogleMapV3.prototype = {
    initialize: function () {
        if (this._startPoint == null)
            this._startPoint = new google.maps.LatLng(38.285789999999999, -122.01031);

        var myOptions = {
            zoom: this._zoom,
            maxZoom: this._maxZoom,
            center: this._startPoint,
            mapTypeId: this._mapType,
            panControl: true,
            zoomControl: true,
            zoomControlOptions: { style: google.maps.ZoomControlStyle.SMALL },
            mapTypeControl: true,
            mapTypeControlOptions: { style: google.maps.MapTypeControlStyle.DROPDOWN_MENU, position: google.maps.ControlPosition.TOP_RIGHT },
            scaleControl: true,
            streetViewControl: true,
            overviewMapControl: true
        };

        this._objMap = new google.maps.Map(this._domMapDiv, myOptions);
        this._geocoder = new google.maps.Geocoder();
        this._bounds = new google.maps.LatLngBounds();

        Sys.Application.add_unload(Function.createDelegate(this, this.mapUnload));

        //this.geocodeOffices();
    },
    mapUnload: function () {
        this.clearMarkers();
        if (this._icons != null) {
            //alert (this._overlays.length);
            for (var i = 0; i < this._icons.length; i++) {
                this._icons[i] = null;
            }
            Array.clear(this._icons);
        }
        if (this._infoWindow != null) {
            google.maps.event.clearInstanceListeners(this._infoWindow);
            this._infoWindow = null;
        }
        this._iconShadow = null;
        this._objMap = null;
        this._domInfoDiv = null;
        this._domMapDiv = null;
        this._callback = null;
        this._showCallback = null;
        this._hideCallback = null;
    },
    clearMarkers: function () {
        if (this._markers != null) {
            if (this._markers.length > 0) {
                //alert (this._overlays.length);
                for (var i = 0; i < this._markers.length; i++) {
                    if (this._markers[i].get_marker() != null) {
                        var marker = this._markers[i].get_marker();
                        google.maps.event.clearInstanceListeners(marker);
                        marker.setMap(null);
                        marker = null;
                        this._markers[i].set_marker(null);
                    }

                    this._markers[i].set_object(null);
                    this._markers[i].set_point(null);

                }
                Array.clear(this._markers);

                this._bounds = new google.maps.LatLngBounds();
            }
        }
    },
    set_showCallback: function (cb) {
        this._showCallback = cb;
    },
    set_hideCallback: function (cb) {
        this._hideCallback = cb;
    },
    getMarkers: function () {
        return this._markers;
    },
    setZoom: function (zoom) {
        this._zoomTemp = zoom;
        try { this._objMap.setZoom(this._zoomTemp); } catch (e) { }
        //google.maps.event.addListenerOnce(this._objMap, "idle",
        //Function.createDelegate(this, function () { this._objMap.setZoom(this._zoomTemp); }));
    },
    _geocodePoints: function () {
        while (this._currentIndex < this._markers.length) {
            if (this._markers[this._currentIndex].get_point() == null && this._markers[this._currentIndex].get_address().length > 0) {
                this._geocoder.geocode(
                                        { 'address': this._markers[this._currentIndex].get_address() },
                                        Function.createDelegate(this, this._geocodePoints2));
                return;
            }
            else {
                this._currentIndex++;
            }
        }

        this._showMarkers();
    },
    _geocodePoints2: function (results, status) {
        var point = null;
        if (status == google.maps.GeocoderStatus.OK) {
            for (var i = 0; results[0].types.length > 0 && i < results[0].types.length; i++) {
                if (results[0].types[i] == "street_address") {
                    this._markers[this._currentIndex].set_point(results[0].geometry.location);
                    this._markers[this._currentIndex].set_geocoded();
                    break;
                }
            }
        }
        if (this._markers[this._currentIndex].get_point() == null)
            this._currentIndex++;

        this._geocodePoints();
    },
    showMarkers: function (callback) {
        //this._objMap.setOptions({ draggable: false });

        if (callback)
            this._callback = callback;
        this._geocodePoints();
    },
    _showMarkers: function () {
        if (this._markers.length > 0) {
            for (var i = 0; i < this._markers.length; i++) {
                var m = this._markers[i];
                if (m.get_point() != null) {
                    var point = m.get_point();
                    this._bounds.extend(point);

                    var icon = null;
                    if (m.get_iconIndex() >= 0 && m.get_iconIndex() < this._icons.length)
                        icon = this._icons[m.get_iconIndex()];

                    var marker = new google.maps.Marker({
                        position: point,
                        map: this._objMap,
                        icon: icon,
                        shape: null,
                        shadow: this._iconShadow,
                        zIndex: 1,
                        draggable: m.get_draggable(),
                        title: m.get_title()
                    });

                    if (this._domInfoDiv != null) {
                        var del = Function.createDelegate(this, this.showDetail);
                        google.maps.event.addListener(marker, 'click', function () { del(this); });
                        marker["index"] = i;
                    }

                    m.set_marker(marker);
                }
            }

            var d1 = (this._bounds.getNorthEast().lat() - this._bounds.getSouthWest().lat());
            var delta = d1 * 0.75;
            // shift map up a little to account for icon height
            var pointx = new google.maps.LatLng(this._bounds.getNorthEast().lat() + delta, this._bounds.getNorthEast().lng());
            //this._bounds.extend(pointx);

            this._objMap.fitBounds(this._bounds);
            this._objMap.setCenter(this._bounds.getCenter());

            //alert(this._objMap.getZoom());
            if (this._objMap.getZoom() > this._maxZoom) {
                this._objMap.setZoom(this._maxZoom);
                //alert(this._objMap.getZoom());
            }
            //alert(this._objMap.getZoom());
        }
        else {
            this._domMapDiv.style.display = "none";
        }

        //this._objMap.setOptions({ draggable: true });

        if (this._callback != null) {
            this._callback();
        }
    },
    setIconShadow: function (s) {
        this._iconShadow = s;
    },
    addIcon: function (icon) {
        Array.add(this._icons, icon);
    },
    addMarker: function (m) {
        Array.add(this._markers, m);
    },
    resize: function () {
        google.maps.event.trigger(this._objMap, 'resize');
    },
    panTo: function (point) {
        this._objMap.panTo(point);
    },
    recenter: function () {
        this._objMap.fitBounds(this._bounds);
        this._objMap.setCenter(this._bounds.getCenter());
    },
    hideDetail: function () {
        if (this._tempLocation != null)
            this._objMap.panTo(this._tempLocation);
        if (this._hideCallback != null) {
            this._hideCallback();
        }
    },
    showDetail: function (marker) {
        if (this._infoWindow == null) {
            this._infoWindow = new google.maps.InfoWindow({ content: "" });
            google.maps.event.addListener(this._infoWindow, 'closeclick', Function.createDelegate(this, this.hideDetail));
        }

        if (marker) {
            var i = marker["index"];

            if (this._domInfoDiv != null) {
                if (this._markers[i].get_html() != null && this._markers[i].get_html().length > 0)
                    this._domInfoDiv.innerHTML = this._markers[i].get_html();
                if (this._showCallback != null) {
                    this._showCallback(this._markers[i]);
                }

                this._tempLocation = this._objMap.getCenter();

                this._infoWindow.setContent(this._domInfoDiv);
                this._infoWindow.open(this._objMap, marker);
            }
        }
    }
}

GoogleMapV3.Marker = function (title, html, lat, lng, address, appId, object, iconIndex, draggable) {
    this._title = title;
    this._html = html;
    this._address = address;
    this._appId = appId;
    this._point = null;
    this._geocoded = false;
    this._marker = null;
    this._object = object
    this._iconIndex = -1;
    if (iconIndex != null)
        this._iconIndex = iconIndex;

    this._draggable = false;
    if (draggable != null)
        this._draggable = draggable;

    if (lat != 0 || lng != 0) {
        this.set_point(new google.maps.LatLng(lat, lng));
    }
}
GoogleMapV3.Marker.prototype = {
    was_geocoded: function () {
        return this._geocoded;
    },
    set_geocoded: function () {
        this._geocoded = true;
    },
    get_draggable: function () {
        return this._draggable;
    },
    get_iconIndex: function () {
        return this._iconIndex;
    },
    set_object: function (o) {
        this._object = o;
    },
    get_object: function () {
        return this._object;
    },
    get_appID: function () {
        return this._appId;
    },
    set_point: function (point) {
        this._point = point;
    },
    get_point: function () {
        return this._point;
    },
    get_title: function () {
        return this._title;
    },
    get_html: function () {
        return this._html;
    },
    set_marker: function (m) {
        this._marker = m;
    },
    get_marker: function () {
        return this._marker;
    },
    get_address: function () {
        return this._address;
    }
} 
