﻿google.load("maps", "2");

google.setOnLoadCallback(function() {
    var map = new CoverageMap($('map'), 'http://www.boxertv.dk/CoverageMap/config.json', 'http://www.boxertv.dk/CoverageMap/coverage.json');
    $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapButton').addEvent('click', function() {
        map.search($('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').value);
        return false;
    }.bind(this));
    /* this button isn't used in the danish version
        $('ctl00_ctl00_MainBodyRegion_MainContent_zoomOutMapButton').addEvent('click', function() {
        map.resetZoomAndCenter();
    }); */
    $(document.body).addEvent('unload', function() {
        if (GUnload != 'undefined')
            GUnload();
    });
});

//  CoverageMap class reference
//
//      Description:
//          The CoverageMap represents a Google Maps instance displaying stations and their coverage on a map.
//
//      Initialization functions:
//          initialize()            Loads and configures the GMap
//          Parameters:
//              mapElement          The DOM element to wrap the map in
//              configUri           The URI which returns the config JSON object
//              coverageUri         The URI which returns coverage data
//          loadConfig()            Loads the config JSON object
//          initMarkers()           Creates the marker manager array, and the home marker icon
//          initEvents()            Configures events that occur on the map
//
//      Interaction functions:
//          getCoverage()           Displays the coverage data for a given point on the map
//          Parameters:
//              lng                 The longitude of the point
//              lat                 The latitude of the point
//          resetZoomAndCenter()    Zoom and pan to the initial zoom level and center point
//          resetZoom()             Zoom to the initial zoom level
//          updateHomeMarker()      Moves the home marker
//          Parameters:
//              latlng              The new coordinates for the marker
//          clearHomeMarkers()      Removes the home marker
//
//      Implementation notes:
//          The Marker array might be somewhat confusing. We're only supposed to have one marker, right? Yes,
//          but due to a certain.. unpredictable behavior in Google Maps, excessively fast clicking will result
//          in markers being placed on the map faster than they are removed. And since Google Maps does not have
//          a marker manager, we'll have to use our own.
//
var CoverageMap = new Class({
    initialize: function(mapElement, configSource, coverageUri) {
        this.ConfigUri = configSource;
        this.CoverageUri = coverageUri;
        this.loadConfig(function() {
            /* When config has been loaded, setup map object */
            G_NORMAL_MAP.getMaximumResolution = function() { return parseInt(this.Config.MaxZoom); } .bind(this);
            G_NORMAL_MAP.getMinimumResolution = function() { return parseInt(this.Config.MinZoom); } .bind(this);
            this.Map = new google.maps.Map2(document.getElementById("map"));
            this.Map.setMapType(G_NORMAL_MAP);
            this.Map.addControl(new GSmallMapControl());
            var kml = new GGeoXml(this.Config.GoogleEarthKmlUrl, function(eventArgs) {
                this.Map.addOverlay(kml);
                kml.show();
            } .bind(this));
            this.Map.disableInfoWindow();
            this.initMarkers();
            this.initEvents();
            this.resetZoomAndCenter();
            this.initTileLayer();
        } .bind(this));
    },
    loadConfig: function(onFinished) {
        var cfgRequest = new Request.JSON({ url: this.ConfigUri, onComplete: function(config) {
            this.Config = config;
            onFinished();
        } .bind(this)
        });
        cfgRequest.get();
    },
    initMarkers: function() {
        this.Overlays = new Array();
        this.HomeMarkerIcon = new GIcon();
        this.HomeMarkerIcon.image = this.Config.HomeMarkerUrl;
        this.HomeMarkerIcon.iconSize = new GSize(this.Config.HomeMarkerWidth, this.Config.HomeMarkerHeight);
        this.HomeMarkerIcon.iconAnchor = new GPoint(this.Config.HomeMarkerAnchorX, this.Config.HomeMarkerAnchorY);
    },
    initEvents: function() {
        GEvent.addListener(this.Map, "click", function(overlay, latlng) {
            this.clearHomeMarkers();
            this.updateHomeMarker(latlng);
            this.getCoverage(latlng);
        } .bind(this));
        var searchMapBoxVal = $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').get('value');
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').addEvent('focus', function() {
            if ($('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').get('value') == searchMapBoxVal)
                $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').set('value', '');
        });
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').addEvent('blur', function() {
            if ($('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').get('value') == '')
                $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').set('value', searchMapBoxVal);
        });
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').addEvent('keypress', function(e) {
            if (e.key == 'enter')
                this.search($('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').get('value'));
        } .bind(this));

    },
    initTileLayer: function() {
        var emptyCopyright = new GCopyright(1337, new GLatLngBounds(), 7, 'Boxer.DK');
        var emptyCopyrightCollection = new GCopyrightCollection();
        emptyCopyrightCollection.addCopyright(emptyCopyright);
        this.CoverageTileLayer = new GTileLayer(emptyCopyrightCollection);
        this.CoverageTileLayer.getTileUrl = this.getTileUrl.bind(this);
        this.CoverageTileLayer.isPng = function() { return true; };
        this.CoverageTileLayer.getOpacity = function() { return 0.5; };
        this.CoverageTileOverlay = new GTileLayerOverlay(this.CoverageTileLayer);
        this.Map.addOverlay(this.CoverageTileOverlay);
    },
    getTileUrl: function(tile, zoom) {
        // Our tile layer uses TMS tile addressing, so we need to flip the Y-coordinate
        var tiles = Math.pow(2, zoom);
        var googleY = tiles - tile.y - 1;
        return this.Config.TileLayerBaseUri + zoom + "/" + tile.x + "/" + googleY + ".png";
    },
    getCoverage: function(latlng) {
        var coverageRequest = new Request.JSON({ url: this.CoverageUri, onComplete: function(transmitters) {
        if (transmitters.BestTransmitter != null) {
                $('recommendation').setStyle('display', 'block');
                $(this.Config.BestTransmitterNameElementId).innerHTML = transmitters.BestTransmitter.Name;
                var bestAngle = Math.round(Math.atan2(transmitters.BestTransmitter.Longitude - latlng.lng(), transmitters.BestTransmitter.Latitude - latlng.lat()) * 180 / Math.PI, 0);
                if (bestAngle < 0)
                    bestAngle += 360;
                $(this.Config.BestTransmitterAngleElementId).innerHTML = bestAngle;
                $(this.Config.BestTransmitterElementId).setStyle('display', 'block');
                $(this.Config.NoTransmitterElementId).setStyle('display', 'none');
                var bestTransmitterLatLng = new GLatLng(transmitters.BestTransmitter.Latitude, transmitters.BestTransmitter.Longitude);
                var bestDistance = bestTransmitterLatLng.distanceFrom(latlng);
                $(this.Config.BestTransmitterDistanceElementId).innerHTML = Math.floor(bestDistance / 1000);
                var bestTransmitterLine = new GPolyline(
                    new Array(latlng, bestTransmitterLatLng),
                    this.Config.BestTransmitterLineColor, 3, 1);
                this.Overlays.push(bestTransmitterLine);
                this.Map.addOverlay(bestTransmitterLine);


                if (transmitters.SecondBestTransmitter != null && transmitters.SecondBestTransmitter.Id != transmitters.BestTransmitter.Id) {
                    var secondAngle = Math.round(Math.atan2(transmitters.SecondBestTransmitter.Longitude - latlng.lng(), transmitters.SecondBestTransmitter.Latitude - latlng.lat()) * 180 / Math.PI, 0);
                    if (secondAngle < 0)
                        secondAngle += 360;
                    $(this.Config.SecondBestTransmitterAngleElementId).innerHTML = secondAngle;
                    $(this.Config.SecondBestTransmitterNameElementId).innerHTML = transmitters.SecondBestTransmitter.Name;
                    $(this.Config.SecondBestTransmitterElementId).setStyle('display', 'block');
                    var secondBestTransmitterLatLng = new GLatLng(transmitters.SecondBestTransmitter.Latitude, transmitters.SecondBestTransmitter.Longitude);
                    var secondBestDistance = secondBestTransmitterLatLng.distanceFrom(latlng);
                    $(this.Config.SecondBestTransmitterDistanceElementId).innerHTML = Math.floor(secondBestDistance / 1000);
                    var secondBestTransmitterLine = new GPolyline(
                        new Array(latlng, secondBestTransmitterLatLng),
                        this.Config.SecondBestTransmitterLineColor, 3, 1);
                    this.Overlays.push(secondBestTransmitterLine);
                    this.Map.addOverlay(secondBestTransmitterLine);
                }
                else {
                    $(this.Config.SecondBestTransmitterElementId).setStyle('display', 'none');
                }
            }
            else {
                $('recommendation').setStyle('display', 'block');
                $(this.Config.BestTransmitterElementId).setStyle('display', 'none');
                $(this.Config.SecondBestTransmitterElementId).setStyle('display', 'none');
                $(this.Config.NoTransmitterElementId).setStyle('display', 'block');
            }
            this.zoomToTransmitter();
        } .bind(this)
        });
        coverageRequest.get({ 'latitude': latlng.lat(), 'longitude': latlng.lng() });
    },
    search: function(address) {
        this.clearHomeMarkers();
        var geoCoder = new GClientGeocoder();
        geoCoder.setBaseCountryCode(this.Config.CountryCode);
        geoCoder.getLocations(address, this.handleSearchResponse.bind(this));
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').disabled = true;
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapButton').disabled = true;
    },
    handleSearchResponse: function(response) {
        if (response.Status.code == 200) {
            var placemarks = new Array();
            response.Placemark.each(function(placemark, i) {
                if (placemark.AddressDetails.Country.CountryNameCode.toUpperCase() == this.Config.CountryCode.toUpperCase()) {
                    placemarks[placemarks.length] = placemark;
                }
                else //new
                {
                    $('results_loading').setStyle('display', 'none');
                    $('results_placemarks').setStyle('display', 'none');
                    $('ctl00_ctl00_MainBodyRegion_MainContent_results_noresults').setStyle('display', 'block');
                    $(this.Config.BestTransmitterElementId).setStyle('display', 'none');
                    $(this.Config.SecondBestTransmitterElementId).setStyle('display', 'none');
                    $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').disabled = false;
                    $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapButton').disabled = false;
                } //endnew
            } .bind(this));

            if (placemarks.length > 0) {
                $('placemarks_firstresult').innerHTML = placemarks[0].address.replace(', ' + placemarks[0].AddressDetails.Country.CountryName, '');
                $('results_loading').setStyle('display', 'none');
                $('results_placemarks').setStyle('display', 'block');
                $('ctl00_ctl00_MainBodyRegion_MainContent_results_noresults').setStyle('display', 'none');
                var latlng = new GLatLng(placemarks[0].Point.coordinates[1], placemarks[0].Point.coordinates[0]);
                this.updateHomeMarker(latlng);
                this.getCoverage(latlng);
            }
            else {
                $('results_loading').setStyle('display', 'none');
                $('results_placemarks').setStyle('display', 'none');
                $('ctl00_ctl00_MainBodyRegion_MainContent_results_noresults').setStyle('display', 'block');
            }
        }
        else {
            $('results_loading').setStyle('display', 'none');
            $('results_placemarks').setStyle('display', 'none');
            $('ctl00_ctl00_MainBodyRegion_MainContent_results_noresults').setStyle('display', 'block');
        }
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapBox').disabled = false;
        $('ctl00_ctl00_MainBodyRegion_MainContent_searchMapButton').disabled = false;

    },
    resetZoomAndCenter: function() {
        this.Map.setCenter(new GLatLng(this.Config.InitialMapCenterLatitude, this.Config.InitialMapCenterLongitude));
        this.Map.setZoom(Number(parseInt(this.Config.MinZoom)));
    },
    updateHomeMarker: function(latlng) {
        var newMarker = new GMarker(latlng, { icon: this.HomeMarkerIcon });
        this.Map.addOverlay(newMarker);
        this.Overlays.push(newMarker);
        this.HomeMarker = newMarker;
    },
    clearHomeMarkers: function() {
        this.Overlays.forEach(function(marker) {
            this.Map.removeOverlay(marker);
        } .bind(this));
        this.Overlays = new Array();
    },
    zoomToTransmitter: function() {
        if (this.Overlays.length <= 1 || this.HomeMarker == null)
            return;
        this.Map.setCenter(this.HomeMarker.getLatLng());
        this.Map.setZoom(parseInt(this.Config.MaxZoom));
    }
});