﻿//*****************************************
function StringBuffer() {
    this.buffer = [];
}

StringBuffer.prototype.append = function append(string) {
    this.buffer.push(string);
    return this;
};

StringBuffer.prototype.toString = function toString() {
    return this.buffer.join("");
};
//*****************************************


var _stateBag = new Object();

function RemoveOverlay(overlay, map) {
    map.removeOverlay(overlay);
}

function RemoveOverlayInState(overlay, map) {
    map.removeOverlay(_stateBag[overlay]);
}

function AddDirectionsAsync(gMap, gMapID, from, to, directionsTextDivId) {

    //Verificamos se jah existe uma direction com o ID. Se existir removemos.
    if (_stateBag[gMapID] != null) {
        _stateBag[gMapID].clear();
    }

    if (document.getElementById(directionsTextDivId).style.display == 'none') {
        document.getElementById(directionsTextDivId).style.display = 'block';
    }

    var handleErrors = function() {
        alert("Não foi possível sugerir uma rota para este trajeto. Tente ser mais específico.");
    };

    var gdir = new GDirections(gMap, document.getElementById(directionsTextDivId));
    GEvent.addListener(gdir, "error", handleErrors);

    gdir.load("from: " + from + " to: " + to, { "locale": "pt-BR" });

    // Adicionamos a direction no bag
    _stateBag[gMapID] = gdir;
}

function getPolylinePoints(p) {
    var pLinePoints = Array();
    for (var n = 0; n < p.getVertexCount(); n++) {
        pLinePoints.push(p.getVertex(n));
    }
    return pLinePoints;
}

function setZoom(map, km) {

    var zoom = 0;

    if (km < 0.65)
        zoom = 16;
    else if (km < 1.12)
        zoom = 15;
    else if (km < 1.6)
        zoom = 14;
    else if (km < 3.2)
        zoom = 13;
    else if (km < 4.8)
        zoom = 12;
    else if (km < 11.2)
        zoom = 11;
    else if (km < 22.5)
        zoom = 10;
    else if (km < 48)
        zoom = 9;
    else if (km < 96)
        zoom = 8;
    else
        zoom = 7;

    map.setZoom(zoom);
}

function PixelsPerKm(lat, zoom) {
    // width of the world in pixels
    var c = 256 * Math.pow(2, zoom);
    // equatorial circumpherence of the world in Km    
    var d = 12756.274 * Math.PI;
    // circumpherence at this latitude [cos() uses radians]
    d = d * Math.cos(lat * Math.PI / 180);
    // pixels per Km
    return c / d;
}

// gPolygonId = Id da circunferencia que sera criada.
// map = Mapa no qual sera desenhada a circunferencia.
// centerMarker = Marker que sera o centro da circunferencia.
// radius = Raio da circunferencia em KM.
function DrawFilledCircle(gPolygonId, map, centerMarker, radius) {

    var zoom = map.getZoom();

    radius = radius * PixelsPerKm(centerMarker.getPoint().lat(), zoom); // em pixels

    var normalProj = G_NORMAL_MAP.getProjection();

    var centerPt = normalProj.fromLatLngToPixel(centerMarker.getPoint(), zoom);

    var circlePoints = Array();

    with (Math) {

        for (var a = 0; a <= 360; a += 4) {
            var aRad = a * (PI / 180);                      // conversao pra radianos 180 = PI
            var y = centerPt.y + radius * sin(aRad);    // y = r . sen(a)
            var x = centerPt.x + radius * cos(aRad);    // x = r . cos(a)

            var p = new GPoint(x, y);

            circlePoints.push(normalProj.fromPixelToLatLng(p, zoom));
        }
    }

    var circleLine = new GPolygon(circlePoints, "#005ffe", 1, 0.7, "#96BDFE", 0.5);

    map.addOverlay(circleLine);

    // Salvamos o polygon no state	
    _stateBag[gPolygonId] = circleLine;
}

function ReadDirectionsInfo(dirObj) {

    var status = dirObj.getStatus();
    var bounds = dirObj.getBounds();

    var copyrightHTML = dirObj.getCopyrightsHtml();
    var summaryHTML = dirObj.getSummaryHtml();
    var distance = dirObj.getDistance();
    var duration = dirObj.getDuration();
    var polyline = dirObj.getPolyline();

    var pLinePoints = getPolylinePoints(polyline);

    var numGeoCodes = dirObj.getNumGeocodes();
    var startPoint = dirObj.getGeocode(0);
    var endPoint = dirObj.getGeocode(numGeoCodes - 1);

    var latStart = startPoint.Point.coordinates[1];
    var lngStart = startPoint.Point.coordinates[0];

    var lineString = new StringBuffer();
    for (n = 0; n < pLinePoints.length; n++) {
        var p = pLinePoints[n];
        lineString.append(p.lat().toFixed(6) + ',' + p.lng().toFixed(6) + 'x');
    }

    var info = new Object();

    info["Status"] = status;
    info["CopyrightHTML"] = copyrightHTML;
    info["SummaryHTML"] = summaryHTML;
    info["Distance"] = distance.meters;
    info["Duration"] = duration.seconds;
    info["GeocodesNumber"] = numGeoCodes;
    info["StartLatLng"] = startPoint.Point.coordinates[1] + "," + startPoint.Point.coordinates[0];
    info["EndLatLng"] = endPoint.Point.coordinates[1] + "," + endPoint.Point.coordinates[0];
    info["BoundSWLatLng"] = bounds.getSouthWest().lat() + "," + bounds.getSouthWest().lng();
    info["BoundNELatLng"] = bounds.getNorthEast().lat() + "," + bounds.getNorthEast().lng();
    info["PolylinePoints"] = lineString.toString();

    return info;
}

function GetDirectionsInfoAsync(gMap, from, to, gMapID, txtResult) {

    if ((from != null && from != "") && (to != null && to != "")) {

        //Verificamos se jah existe uma direction com o ID. Se existir removemos.
        if (_stateBag[gMapID] != null) {
            _stateBag[gMapID].clear();
        }

        var gdir = new GDirections(gMap);

        var handleDirectionsErrors = function() {
            alert("Não foi possível sugerir uma rota para este trajeto. Tente ser mais específico.");
        };

        var onDirectionsLoad = function() {
            // Setting the results           
            var info = ReadDirectionsInfo(gdir);
            document.getElementById(txtResult).value = info["Distance"] + "#" + info["Duration"] + "#" + info["PolylinePoints"];
        };

        GEvent.addListener(gdir, "error", handleDirectionsErrors);
        GEvent.addListener(gdir, "load", onDirectionsLoad);

        gdir.load("from: " + from + " to: " + to, { "locale": "pt-BR" });

        _stateBag[gMapID] = gdir;
    }
}

function AddMarkersRota(gMap, lat1, lng1, lat2, lng2, txtSaida, txtChegada) {

    if (_stateBag["RotaSaida"] != null) {
        gMap.removeOverlay(_stateBag["RotaSaida"]);
    }
    if (_stateBag["RotaChegada"] != null) {
        gMap.removeOverlay(_stateBag["RotaChegada"]);
    }

    var baseIcon = new GIcon();
    baseIcon.shadow = "http://www.google.com/mapfiles/shadow50.png";
    baseIcon.iconSize = new GSize(20, 34);
    baseIcon.shadowSize = new GSize(37, 34);
    baseIcon.iconAnchor = new GPoint(9, 34);
    baseIcon.infoWindowAnchor = new GPoint(9, 2);
    baseIcon.infoShadowAnchor = new GPoint(18, 25);

    var startIcon = new GIcon(baseIcon, "http://maps.google.com/mapfiles/dd-start.png", null, "");
    var endIcon = new GIcon(baseIcon, "http://maps.google.com/mapfiles/dd-end.png", null, "");

    var marker1 = new GMarker(new GLatLng(lat1, lng1), { icon: startIcon, draggable: false, bouncy: false });
    gMap.addOverlay(marker1);

    GEvent.addListener(marker1, "click", function() {
        marker1.openInfoWindowHtml(txtSaida, { maxWidth: 200 });
    });

    var marker2 = new GMarker(new GLatLng(lat2, lng2), { icon: endIcon, draggable: false, bouncy: false });
    gMap.addOverlay(marker2);

    GEvent.addListener(marker2, "click", function() {
        marker2.openInfoWindowHtml(txtChegada, { maxWidth: 200 });
    });

    SetBoundsZoomAndCenter(gMap, lat1, lng1, lat2, lng2);

    _stateBag["RotaSaida"] = marker1;
    _stateBag["RotaChegada"] = marker2;
}

function SetBoundsZoomAndCenter(gMap, lat1, lng1, lat2, lng2) {
    // Setamos o zoom de modo a vermos os 2 markers
    var ne = new GLatLng((lat1 > lat2 ? lat1 : lat2), (lng1 > lng2 ? lng1 : lng2));
    var sw = new GLatLng((lat1 < lat2 ? lat1 : lat2), (lng1 < lng2 ? lng1 : lng2));

    var bounds = new GLatLngBounds(sw, ne);

    gMap.setZoom(gMap.getBoundsZoomLevel(bounds));

    // setamos o centro
    gMap.panTo(bounds.getCenter());
}

function AddGGeoXml(gMap, urlXml) {

    var geoXml = new GGeoXml(urlXml);
    gMap.addOverlay(geoXml);

    GEvent.addListener(geoXml, "load", function() {
        if (geoXml.loadedCorrectly()) {
            // Setting the map default viewport
            // geoXml.gotoDefaultViewport(gMap);            
        }
        else {
            alert("Oops... O Google maps não conseguiu carregar todas as caronas.");
        }
    });
}