﻿//<![CDATA[

// Google Map object
var mapInfo;
var markup = null;
var editPoint = null;
var editLine = null;

// Initialization logic
function loadMap() {

    if (debugging()) {
        alert('loadMap start');
    }

    var mapOptions = {
        mapTypeId: google.maps.MapTypeId.HYBRID,
        mapTypeControlOptions: { position: google.maps.ControlPosition.TOP_RIGHT, style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR},
        navigationControl: { position: google.maps.ControlPosition.TOP_LEFT, style: google.maps.NavigationControlStyle.ZOOM_PAN},
        scaleControl: true
    }
       
    mapInfo = new google.maps.Map(document.getElementById("map"),mapOptions);

    setMapExtent();

    var ddlLayer = GetElement('ddlLayer');
    if (ddlLayer != null) {
        addLayer(ddlLayer.value);
    }

    if (debugging()) {
        alert('after setMapExtent');
    }

    google.maps.event.addListener(mapInfo, "click", function(event) {

        if (debugging()) {
            alert('in click');
        }

        SetCoord(event.latLng, 'Cursor');
        
        UpdateDrawing(event);
    });

    google.maps.event.addListener(mapInfo, "bounds_changed", function() {

        if (debugging()) {
            alert('in bounds_changed');
        }

        SetCoord(mapInfo.getBounds().getSouthWest(), 'Minimum');
        SetCoord(mapInfo.getBounds().getNorthEast(), 'Maximum');
        SetCoord(mapInfo.getBounds().getCenter(), 'Cursor');

    });

    google.maps.event.addListener(mapInfo, "zoom_changed", function() {

        if (debugging()) {
            alert('in zoom_changed');
        }

        var mzl = GetElement('hidMapZoomLevel');
        mzl.value = mapInfo.getZoom();
        
    });
    if (debugging()) {
        alert('loadMap end');
    }
}

function UpdateDrawing(event) {

    var dt = GetElement('txtDrawType');
    if (!dt) {
        return;
    }

    var dm = GetElement('txtDrawMode');
    var cp = GetElement('txtCurrentPoint');    
    var cs = GetElement('txtDrawing');

    var pts = new Array()
    if (cs.value != '') {
        pts = cs.value.split(',');
    } 
    var i;

    if (cp.value == '') {
        cp.value = pts.length;
    }    
    
    if (dm.value == 'add') {

        cs.value = '';
        
        // use everything up to the current point
        for (i = 0; i < parseInt(cp.value); i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }

        // add the new point            
        if (cs.value != '') {
            cs.value += ',';
        }
        cs.value += event.latLng.lng();
        cs.value += ' ';
        cs.value += event.latLng.lat();

        // use everything after the current point
        for (i = parseInt(cp.value); i < pts.length; i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }

        cp.value = parseInt(cp.value) + 1;
    }
    else if (dm.value == 'edit') {
        cs.value = '';

        // use everything up to the current point
        for (i = 0; i < parseInt(cp.value) - 1; i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }

        // use the new point in place of the existing point
        if (cs.value != '') {
            cs.value += ',';
        }
        cs.value += event.latLng.lng();
        cs.value += ' ';
        cs.value += event.latLng.lat();

        // use everything after the current point
        for (i = cp.value; i < parseInt(cp.length); i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }
    }
    else if (dm.value == 'delete') {

        cs.value = '';

        // use everything before the current point
        for (i = 0; i < parseInt(cp.value) - 1; i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }

        // use everything after the current point
        for (i = parseInt(cp.value); i < pts.length; i++) {
            if (cs.value != '') {
                cs.value += ',';
            }
            cs.value += pts[i];
        }

        cp.value = parseInt(cp.value) - 1;
    }
    else {
        // select closest vertex

        var distance;
        var closest = 999;

        for (i = 0; i < pts.length; i++) {
            var ll = pts[i].split(' ');
            distance = Math.sqrt(Math.pow(ll[0] - event.latLng.lng(), 2) + Math.pow(ll[1] - event.latLng.lat(), 2));
            if (distance < closest) {
                closest = distance;
                cp.value = i;
            }            
        }
    }
    
    if (markup) {
        markup.setMap(null); // remove existing markup from map
    }
    if (editPoint) {
        editPoint.setMap(null);
    }
    if (editLine) {
        editLine.setMap(null);
    }
    
    var pathArray = LLArrayFromCoords(cs.value);

    if (pathArray.length <= 1 || dt.value == 'point') {
        var markerOptions = {
            map: mapInfo,
            position: pathArray[0],
            clickable: true
        }
        markup = new google.maps.Marker(markerOptions);        
    }
    else if (pathArray.length <= 2 || dt.value == 'line') {
        var lineOptions = {
            geodesic: true,
            map: mapInfo,
            path: pathArray,
            strokeColor: '#ffffff',
            strokeOpacity: 1.0,
            strokeWeight: 3,
            clickable: true
        }
        markup = new google.maps.Polyline(lineOptions);
    }
    else {

        pathArray[pathArray.length] = pathArray[0];
        
        var polyOptions = {
            fillColor: '#ffffff',
            fillOpacity: 0.5,
            geodesic: true,
            map: mapInfo,
            paths: pathArray,
            strokeColor: '#ffffff',
            strokeOpacity: 1.0,
            strokeWeight: 3,
            clickable: true
        }
        markup = new google.maps.Polygon(polyOptions);
    }

    google.maps.event.addListener(markup, "click", function(event) {

        if (debugging()) {
            alert('in click');
        }

        SetCoord(event.latLng, 'Cursor');

        UpdateDrawing(event);
    });

    if (pathArray.length >= 1) {
        var editPointOptions = {
            map: mapInfo,
            position: pathArray[parseInt(cp.value)],
            draggable: true,
            icon: new google.maps.MarkerImage('images/map_red.png', new google.maps.Size(16,16), new google.maps.Point(8,8), new google.maps.Point(8,8), 0.5)
        }
        editPointOptions = new google.maps.Marker(editPointOptions);

        google.maps.event.addListener(markup, "dragend", function(event) {

            if (debugging()) {
                alert('in click');
            }

            var dm = GetElement('txtDrawMode');
            if (!dm) {
                return;
            }

            var save = dm.value;
            dm.value = 'edit';
            UpdateDrawing(event);
            dm.value = save;
        });
    }

    if (pathArray.length >= 2 && (parseInt(cp.value) + 1 < pathArray.length || dt.value == 'polygon')) {
        var lineOptions = {
            geodesic: true,
            map: mapInfo,
            path: [pathArray[parseInt(cp.value)], pathArray[(parseInt(cp.value) + 1) % pathArray.length]],
            strokeColor: '#ff0000',
            strokeOpacity: 1.0,
            strokeWeight: 3,
            clickable: true
        }
        markup = new google.maps.Polyline(lineOptions);
    }
}

function LLArrayFromCoords(cs) {

    if (cs.indexOf(',') > 0) {
        var arr = cs.split(',');
        var i;
        for (i = 0; i < arr.length; i++) {
            var lng = arr[i].split(' ')[0];
            var lat = arr[i].split(' ')[1];
            var ll = new google.maps.LatLng(lat, lng);
            arr[i] = ll;
        }

        return arr;
    }
    else {
        var lng = cs.split(' ')[0];
        var lat = cs.split(' ')[1];
        return new Array ( new google.maps.LatLng(lat, lng) );
    }
}

// used to get to any ASPX controls, which have a prefix 
function GetElement(strField) {
    var strControlPrefix = BaseID();
    return document.getElementById(strControlPrefix + strField);
}

// Get a LatLng object, based on data in a certain lat/long fields on the page
function GetCoord(strField) {

    var lat, lng;

    elem = GetElement('coord' + strField + 'Latitude');
    if (elem) {
        lat = UnformatCoord(elem.value);
    }

    elem = GetElement('coord' + strField + 'Longitude');
    if (elem) {
        lng = UnformatCoord(elem.value);
    }

    return new google.maps.LatLng(lat, lng);
}

// Set a specific pair of lat/long fields based on the coordinate provided
function SetCoord(coord, strField) {

    var elem;

    elem = GetElement('coord' + strField + 'Latitude');
    if (elem) {
        elem.value = FormatCoord(coord.lat());
    }

    elem = GetElement('coord' + strField + 'Longitude');
    if (elem) {
        elem.value = FormatCoord(coord.lng());
    }

}

function DisplayFormat() {
    var elem = GetElement("hidFormat");
    if (elem.value == "1") {
        return "d";
    }
    else if (elem.value == "2") {
        return "dm";
    }
    else {
        return "dms";
    }
}

function DegreeSymbol() {
    return "\u00B0";
}

function MinuteSymbol() {
    return "'";
}

function SecondSymbol() {
    return "\"";
}

// Take decimal coordinate and convert to the current display type
function FormatCoord(coord) {

    var strSign;
    var deg, min, sec, remainder;
    var strResult;
    
    if (coord < 0) {
        strSign = "-";
    }
    else {
        strSign = "";
    }
    
    deg = 0;
    min = 0;
    sec = 0;
    
    coord = Math.abs(Math.round(coord * 100000) / 100000);
  
    if (DisplayFormat() == "d") {
        deg = coord;
    } else {
        deg = Math.floor(coord);
    }
    remainder = (coord - deg) * 60;
    
    if (DisplayFormat() == "dm") {
        min = Math.round(remainder * 1000) / 1000;
    } else {
        min = Math.floor(remainder);
    }
    remainder = (remainder - min) * 60;
    
    sec = Math.round(remainder * 1000) / 1000;
    
    strResult = strSign + deg + DegreeSymbol();
    if (DisplayFormat() == "d") {
        return strResult;
    }
    strResult = strResult + " " + min + MinuteSymbol();
    if (DisplayFormat() == "dm") {
        return strResult;
    }
    strResult = strResult + " " + sec + SecondSymbol();
    return strResult;
}

// take display coordinate and convert to a decimal
function UnformatCoord(str) {
    var sign;
    
    str = str.replace(DegreeSymbol(),"");
    str = str.replace(MinuteSymbol(),"");
    str = str.replace(SecondSymbol(),"");
    
    var splitResult;
    splitResult = str.split(" ");

    if (DisplayFormat() == "d" && splitResult.Length > 1) {
        alert('Invalid coordinate.  For the "degrees" format, specify one number.');
        return 0;
    }
    if (DisplayFormat == "dm" && splitResult.Length > 2) {
        alert('Invalid coordinate.  For the "degrees minutes" format, specify two numbers separated by a space.');
        return 0;
    }
    if (DisplayFormat == "dms" && splitResult.Length > 3) {
        alert('Invalid coordinate.  For the "degrees minutes seconds" format, specify three numbers separated by spaces.');
        return 0;
    }    
    
    var result = 0;
    for (i=0; i<splitResult.length; i++) {

        if (isNaN(splitResult[i])) {
            alert('Invalid coordinate.  Non-numeric value provided.');
            return 0;        
        }
        if (i == 0) {
            if (splitResult[i] < -180 || splitResult[i] > 180) {
                alert('Invalid coordinate.  The degrees values must be between -180 and 180.');
                return 0;                
            } else {
                result += Number(splitResult[i]);
                if (result >= 0) {
                    sign = 1;
                }
                else {
                    sign = -1;
                }
            }
        }
        if (i == 1) {
            if (splitResult[i] < 0 || splitResult[i] >= 60) {
                alert('Invalid coordinate.  The minutes value must be between 0 and 60.');
                return 0;                
            }
            else {
                result += Number(splitResult[i] / 60 * sign);
            }
        }
        if (i == 2) {
            if (splitResult[i] < 0 || splitResult[i] >= 60) {
                alert('Invalid coordinate.  The seconds value must be between 0 and 60.');
                return 0;                
            }
            else {
                result += Number(splitResult[i] / 3600 * sign);
            }
        }
    }
    return result;
}

// Return a bool indicating whether the user wants to view debug messages
function debugging() {
    return parent.document.URL.indexOf("debug") > 0
}

// View the current KML file
function viewInGoogleEarth() {
    window.location = KmlUrl('all', '');
}

// this variable will be filled with the URL of the file that contains the KML file
var strResponseURL;

// Add a KML file to the map
function addLayer(type) {

    var url = KmlUrl(type, '')

    if (!url || url == '' || url.indexOf('localhost') >= 0) {
        return null;
    }
    
    // appending this will cause the call to return the name of the KML file, instead of returning the KML file itself
    // Google Maps v3 seems to have problems trying to get a KML file that doesn't have a KML extension
    url = url + "&getURL=y";
    
    if (debugging()) {
        alert('addLayer ' + type + ' = ' + url);
    }
    
    document.getElementById('loading').innerHTML = 'Loading...';

    if (debugging()) {
        alert('before load');
    }

    // AJAX call to build KML and get name of temporary filename
    var xhr = new XHR();
    if (xhr == null) return;
    xhr.getRequest(url, 'text', function(str) { 

        if (debugging()) {
            alert('temporary filename=' + str);
        }    
        // load the temporary KML
        var kmlObj = new google.maps.KmlLayer(str, { preserveViewport: true });
        kmlObj.setMap(mapInfo);
        
        if (debugging()) {
            alert('after load');
        }
        
        document.getElementById('loading').innerHTML = '';
    });
    
}

// Get the URL for the requested KML
function KmlUrl(type, limit) {

    var strField

    if (type == 'all') {
        strField = 'hidKmlUrlAll';
    }
    else {
        strField = 'hidKmlUrl';
    }
    var value = GetElement(strField).value;
    return value.replace('&amp;', '&');
}

// Update map to include the min/max coords currently displayed
function setMapExtent() {

    var zl = GetElement('hidMapZoomLevel').value;
    var ctr = GetCoord('Cursor');
    var sw = GetCoord('Minimum');
    var ne = GetCoord('Maximum');

    if (zl != '') {
        centerMap();
        mapInfo.setZoom(parseInt(zl));
    }
    else {
        if (sw.lng() > ne.lng()) {
            var new_sw = google.maps.LatLng(sw.lat(), ne.lng());
            var new_ne = google.maps.LatLng(ne.lat(), sw.lng());
            sw = new_sw;
            ne = new_ne;
        }
        var bounds = new google.maps.LatLngBounds(sw, ne);

        mapInfo.fitBounds(bounds);
        mapInfo.setZoom(mapInfo.getZoom() + 1); // fitBounds always seems to go out a little bit too far, so zoom in

        SetCoord(bounds.getCenter(), 'Cursor');
    }
    
}

// Reposition map to lat/long specified in current position field
function centerMap() {
    var ll = GetCoord('Cursor');
    mapInfo.setCenter(ll);
}

// Update coordinate of a mooring to current position
function setCoordinate() {
    var ll = GetCoord('Cursor');
    var loc;
    loc = 'setCoordinate.aspx'
    loc += '?mooringID=' + GetElement('ddlBerths').value;
    loc += '&lat=' + FormatCoord(ll.lat());
    loc += '&long=' + FormatCoord(ll.lng());
    loc += '&type=' + GetElement('ddlCoordinateType').value;
    document.getElementById('sc').src = loc;
}
//]]>

