﻿GoogleMap = function(elementId) {
    this.elementId = elementId;
    this.input = null;
    this.mapView = null;
    this.gGeocoder = null;
    this.gMap = null;
    this.gMarkers = new Array();
    this.gDirections = null;

    this.initialize();
};
GoogleMap.prototype = {
    initialize: function() {
        if (GBrowserIsCompatible()) {
            this.input = $get(this.elementId + '_input')

            this.loadMapView();

            this.gMap = new GMap2($get(this.elementId));
            this.gMap.clearOverlays();
            this.gMap.setUIToDefault();

            this.gGeocoder = new GClientGeocoder();

            this.addMapListeners();
            this.addMarkers();

            this.locateByAddress();
        }
    },

    loadMapView: function() {
        this.mapView = Sys.Serialization.JavaScriptSerializer.deserialize(this.input.value);
    },
    saveMapView: function() {
        for (var i = 0; i < this.mapView.Markers.length; i++) {
            var m = this.mapView.Markers[i];
            var marker = this.gMarkers[i];

            var location = marker.getLatLng();

            m.Latitude = location.y;
            m.Longitude = location.x;
        }

        this.mapView.Zoom = this.gMap.getZoom();

        var center = this.gMap.getCenter();
        this.mapView.Center.Latitude = center.y;
        this.mapView.Center.Longitude = center.x;

        this.input.value = Sys.Serialization.JavaScriptSerializer.serialize(this.mapView);
    },
    addMapListeners: function() {
        var self = this;

        GEvent.addListener(
            this.gMap,
            "moveend",
            function() { self.saveMapView(); });

        GEvent.addListener(
            this.gMap,
            "zoomend",
            function() { self.saveMapView(); });
    },
    addMarkers: function() {
        for (var i = 0; i < this.mapView.Markers.length; i++) {
            var m = this.mapView.Markers[i];

            var marker = new GMarker(new GLatLng(m.Latitude, m.Longitude), { draggable: this.mapView.CanEdit });
            Array.add(this.gMarkers, marker);
            this.addMarkerListeners(marker);

            this.gMap.addOverlay(marker);
        }
    },
    addMarkerListeners: function(marker) {
        if (this.mapView.CanEdit) {
            var self = this;

            GEvent.addListener(
                marker,
                "dragstart",
                function() { self.gMap.closeInfoWindow(); });

            GEvent.addListener(
                marker,
                "dragend",
                function() { self.raiseMarkersChangedEvent(); });
        }
    },
    raiseMarkersChangedEvent: function() {
        this.mapView.IsDirty = true;
        this.saveMapView();

        if (this.mapView.OnClientMarkersChangedScript != null &&
            this.mapView.OnClientMarkersChangedScript != '') {
            eval(this.mapView.OnClientMarkersChangedScript + "(" + this.elementId + ")");
        }

        if (this.mapView.PostBackScript != '') {
            eval(this.mapView.PostBackScript);
        }
    },
    locateByAddress: function() {
        if (this.mapView.AddressToFind != null &&
            this.mapView.AddressToFind != '') {

            var self = this;
            this.gGeocoder.getLatLng(this.mapView.AddressToFind, function(point) { self.locateByAddressCallBack(point) });
        }
        else {
            this.setCenter();
        }
    },
    locateByAddressCallBack: function(point) {
        var locationFound = point != null;

        if (locationFound) {
            this.mapView.Center.Latitude = point.y;
            this.mapView.Center.Longitude = point.x;
        }
        else {
            this.mapView.Center.Latitude = 65.802776;
            this.mapView.Center.Longitude = 8.4375;
            this.mapView.Zoom = 3;
        }
        this.setCenter();

        var marker = new GMarker(new GLatLng(this.mapView.Center.Latitude, this.mapView.Center.Longitude), { draggable: this.mapView.CanEdit });
        this.addMarkerListeners(marker);
        this.gMap.addOverlay(marker);

        Array.add(this.gMarkers, marker);

        var m = new Object();
        m.Latitude = this.mapView.Center.Latitude;
        m.Longitude = this.mapView.Center.Longitude;
        m.Key = this.mapView.AddressToFindKey;
        Array.add(this.mapView.Markers, m);

        this.mapView.IsDirty = true;
        this.saveMapView();
        
        if (locationFound) {
            if (this.mapView.OnClientLocateByAddressSucceededScript != null &&
                this.mapView.OnClientLocateByAddressSucceededScript != '') {
                eval(this.mapView.OnClientLocateByAddressSucceededScript + "(" + this.elementId + ")");
            }
        }
        else {
            if (this.mapView.OnClientLocateByAddressFailedScript != null &&
                this.mapView.OnClientLocateByAddressFailedScript != '') {
                eval(this.mapView.OnClientLocateByAddressFailedScript + "(" + this.elementId + ")");
            }
        }
    },
    setCenter: function() {
        var center = new GLatLng(this.mapView.Center.Latitude, this.mapView.Center.Longitude);
        this.gMap.setCenter(center, this.mapView.Zoom);
    },
    showDirections: function(from, to, directionsPanel) {
        if (this.gDirections == null) {
            this.gDirections = new GDirections(this.gMap, directionsPanel);

            var self = this;
            GEvent.addListener(this.gDirections, "error", function() { self.handleErrors(); });
        }
        this.gDirections.clear();
        this.gDirections.load("from: " + from + " to: " + to);
    },
    handleErrors: function() {
        if (this.mapView.OnClientDirectionsFailedScript != null &&
            this.mapView.OnClientDirectionsFailedScript != '') {
            var code = this.gDirections.getStatus().code;
            eval(this.mapView.OnClientDirectionsFailedScript + "(" + code + ")");
        }
    }
};
