﻿
Type.registerNamespace("MarkerMap");

MarkerMap.Map = function (element) {
    MarkerMap.Map.initializeBase(this, [element]);

    this.map = null;
    this.markers = new Array();
    this.infoWindows = new Array();
    this.markerClusterer = null;
    this.minZoom = null;
    this.maxZoom = null;
    this.centerLat = null;
    this.centerLng = null;
    this.data = null;
    this.displayControls = null;
    this.draggable = null;
    this.useClustering = null;
}

MarkerMap.Map.prototype = {
    initialize: function () {
        Sys.Debug.trace("Map begin init");
        MarkerMap.Map.callBaseMethod(this, 'initialize');

        this.initMap();

        Sys.Debug.trace("Map end init");
    },
    initMap: function () {
        if (!this.minZoom) this.minZoom = 2; // how far can zoom out (lower = more)
        if (!this.maxZoom) this.maxZoom = 20; // how far can zoom in (higher = further)
        if (!this.centerLat) this.centerLat = 25;
        if (!this.centerLng) this.centerLng = 0;

        var $mapContainer = $("#MapContainer");

        // show map container
        $mapContainer.show();

        // init map
        var myLatlng = new google.maps.LatLng(this.centerLat, this.centerLng);
        var myOptions = {
            zoom: 2,
            minZoom: this.minZoom,
            maxZoom: this.maxZoom,
            center: myLatlng,
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            streetViewControl: false,
            mapTypeControl: false,
            zoomControl: this.displayControls == "True",
            draggable: this.draggable == "True",
            styles: [{
                featureType: "poi",
                elementType: "labels",
                stylers: [{
                    visibility: "off"
                }]
            }]
        }

        // if useClustering is set to false, set the minimum threshold for clustering to occur to 1000
        this.minimumClusterSize = this.useClustering == "True" ? 2 : 1000;

        this.map = new google.maps.Map(document.getElementById("MapCanvas"), myOptions);

        function CreateQuadKey(x, y, zoom) {
            var quad = "";
            for (var i = zoom; i > 0; i--) {
                var mask = 1 << (i - 1); // the level
                var cell = 0;   // this stores the digit for this level
                if ((x & mask) != 0)
                    cell++;
                if ((y & mask) != 0)
                    cell += 2;
                quad += cell;  // add this level to the end of our key
            }
            return quad;
        }

        // set custom map type tiles
        var abtMapOptions = {
            //            getTileUrl: function (coord, zoom) {
            //                return Root + "App_Atom/img/map/" + CreateQuadKey(coord.x, coord.y, zoom) + ".png";
            //            },
            //            tileSize: new google.maps.Size(256, 256),
            maxZoom: this.maxZoom,
            minZoom: this.minZoom
        };

        //var abtMapType = new google.maps.ImageMapType(abtMapOptions);

        //attach the abt map type to the map's registry
        // this.map.mapTypes.set('abtMapType', abtMapType);

        //set the map to use the abt map type
        //this.map.setMapTypeId('abtMapType');

        this.map.setMapTypeId(google.maps.MapTypeId.ROADMAP);


        // plot declarativly supplied data
        if (this.data != null && this.data != "") {

            var jsonData = JSON.parse(this.data); //$.parseJSON(this.data);

            for (var i = 0; i < jsonData.length; i++) {
                jsonData[i].Title = this.getValidTitle(jsonData[i].Title);
            }

            this.refreshMap(jsonData);
        }
    },
    plot: function (results) {

        this.refreshMap(results);
    },
    getValidTitle: function (title) {
        if (title == null || title == "") {
            title = "[no title]";
        }
        return title;
    },
    refreshMap: function (results) {

        this.markers = new Array();
        this.infoWindows = new Array();

        //custom marker image
        var singleImage = new google.maps.MarkerImage(Root + 'App_Atom/img/global/cursor-red-sm.png',
                new google.maps.Size(17, 16),
                new google.maps.Point(0, 0),
                new google.maps.Point(0, 16));

        var clusterImage = [[{
            url: Root + 'App_Atom/img/global/cursor-red.png',
            height: 30,
            width: 32,
            anchor: [0, 17],
            textSize: 10
        }, {
            url: Root + 'App_Atom/img/global/cursor-red.png',
            height: 30,
            width: 32,
            anchor: [0, 17],
            textSize: 10
        }, {
            url: Root + 'App_Atom/img/global/cursor-red.png',
            height: 30,
            width: 32,
            anchor: [0, 17],
            textSize: 10
        }]];

        var shape = {
            coord: [8, 8, 8],
            type: 'circle'
        };

        var windowStyle = {
            background: "#ffffff no-repeat",
            width: "180px",
            border: "1px solid #444444",
            padding: "5px"
        }

        if (this.markerClusterer) {
            this.markerClusterer.clearMarkers();
        }

        if (results == null) return;

        var markerCount = 0;
        for (var i = 0; i < results.length; i++) {

            var resultGroup = results[i];
            
            if (resultGroup.JsonMapPoints != null && resultGroup.JsonMapPoints != '') {
                var points = eval(resultGroup.JsonMapPoints);

                var k = 0;
                resultGroup.MapPoints = new Array();
                while (k < points.length) {

                    resultGroup.MapPoints[k] = { Lat: points[k].latitude, Lng: points[k].longitude };
                    k++;
                }
            }

            if (resultGroup.MapPoints && resultGroup.MapPoints.length > 0) {

                for (var j = 0; j < resultGroup.MapPoints.length; j++) {

                    var resultSubPoint = resultGroup.MapPoints[j];

                    // create new marker
                    var marker = new google.maps.Marker({
                        position: new google.maps.LatLng(resultSubPoint.Lat, resultSubPoint.Lng),
                        documentTitle: resultGroup.Title,
                        absoluteUrl: resultGroup.AbsoluteUrl,
                        icon: singleImage,
                        shape: shape
                    });

                    // add marker to collection
                    this.markers[markerCount] = marker

                    // create new info window
                    //                    var infowindow = new InfoBox({
                    //                        content: formatMarkerWindow(results[i]),
                    //                        disableAutoPan: false,
                    //                        maxWidth: 180,
                    //                        boxStyle: windowStyle,
                    //                        pixelOffset: new google.maps.Size(20, -30)
                    //                    });
                    var infowindow = new google.maps.InfoWindow({
                        content: formatMarkerWindow(results[i]),
                        disableAutoPan: false,
                        maxWidth: 180
                    });

                    var clusterWindow = new google.maps.InfoWindow();

                    // add info window to collection
                    this.infoWindows[markerCount] = infowindow;

                    google.maps.event.addListener(marker, 'mouseover', Function.createDelegate({ map: this.map, markerPoint: marker, popup: infowindow, infoWindows: this.infoWindows },
                        function () {
                            var i;

                            for (i = 0; i < this.infoWindows.length; i++) {
                                this.infoWindows[i].close();
                            }

                            clusterWindow.close();

                            this.popup.open(this.map, this.markerPoint);
                        }
                    ));

                    // hover events for an external list related to each marker
                    google.maps.event.addListener(marker, 'mouseover', Function.createDelegate({ resultItem: results[i] },
                        function () {
                            $('#' + this.resultItem.ID).toggleClass('highlight');
                        }
                    ));
                    google.maps.event.addListener(marker, 'mouseout', Function.createDelegate({ resultItem: results[i] },
                        function () {
                            $('#' + this.resultItem.ID).toggleClass('highlight');
                        }
                    ));

                    // open window on result list hover
                    try {
                        google.maps.event.addDomListener(document.getElementById(results[i].ID), 'mouseover', Function.createDelegate({ map: this.map, markerPoint: marker, popup: infowindow },
                            function () {
                                this.popup.open(this.map, this.markerPoint);
                            }
                        ));
                        google.maps.event.addDomListener(document.getElementById(results[i].ID), 'mouseout', Function.createDelegate({ map: this.map, markerPoint: marker, popup: infowindow },
                            function () {
                                this.popup.close(this.map, this.markerPoint);
                            }
                        ));
                    }
                    catch (ex) { }

                    markerCount++;
                }
            }
        }

        this.markerClusterer = new MarkerClusterer(this.map, this.markers, {
            styles: clusterImage[0],
            maxZoom: 0,
            gridSize: 30,
            minimumClusterSize: this.minimumClusterSize

        });

        var currentCluster = null;
        var windows = this.infoWindows;

        google.maps.event.addListener(this.markerClusterer, "mouseover", function (cluster) {

            if (currentCluster !== cluster) {
                clusterWindow.close();

                var i;

                for (i = 0; i < windows.length; i++) {
                    windows[i].close();
                }

                clusterWindow = new google.maps.InfoWindow({
                    content: 'Click to zoom in and see more',
                    position: cluster.getCenter(),
                    disableAutoPan: false,
                    maxWidth: 180,
                    zIndex: null
                });

                clusterWindow.open(this.map);
            }
        });

        google.maps.event.addListener(this.markerClusterer, "mouseout", function (cluster) {
            clusterWindow.close();
        });

        google.maps.event.addListener(this.markerClusterer, "click", Function.createDelegate({ map: this.map },
            function (cluster) {
                clusterWindow.close(this.map);

                currentCluster = cluster;

                if (this.map.getZoom() > 18) {
                    clusterWindow = new google.maps.InfoWindow({
                        content: formatClusterWindow(cluster),
                        position: cluster.getCenter(),
                        disableAutoPan: false,
                        maxWidth: 180,
                        zIndex: null
                    });

                    clusterWindow.open(this.map);
                }
            }));

        function formatMarkerWindow(result) {
            return '<br \/><a href="' + result.AbsoluteUrl + '">' + result.Title + '<\/a><br \/><br \/>';
        }

        function formatClusterWindow(cluster) {
            var innerHtml = '';
            var markers = cluster.getMarkers();
            for (var i = 0; i < markers.length; i++) {
                innerHtml += '<a href="' + markers[i].absoluteUrl + '">' + markers[i].documentTitle + '<\/a><br \/><br \/>';
            }
            return innerHtml;
        }
    },
    dispose: function () {
        MarkerMap.Map.callBaseMethod(this, 'dispose');
    }
}
MarkerMap.Map.registerClass('MarkerMap.Map', Sys.UI.Behavior);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();


