// =============================================================================
// (c) 2008 MapJack.com
// Author: Bjorn Moren. bjorn@mapjack.com
// =============================================================================

var _map = null;                     // Satellite map
var _dotOverlay = null;              // Dots overlay (GTileLayerOverlay)
var _dotOverlayVisible = true;
var _dotLayer = null
var _avatar = null;                  // Current position (GMarker)
var _beam = null;
var _beamDrag = null;
var _avatarImages = new Array();     // GIF images that makes up the avatar
var _avatarLat = 0;
var _avatarLon = 0;
var _avatarHeading = 0;
var _beamAngle = 90;
var _markers = new Array();

var _beamLength = 35;
var _canDragMap = true;
var _isDraggingBeam = false;
var _beamDragDist = 10;

var _dotOpacityForSat = [7,7,7,7,7,7,7,5,3,3,3,3,5,4,5,8,10,10,10,10];      // Dot opacity for the zoom levels 0 - 10
var _dotOpacityForMap = [3,3,3,3,3,3,3,3,3,3,2,2,3,3,3,3,5,5,5,5];

var _poiMarkers =
[ 
    [18.787851, 98.982410, " POI text 1"],
    [18.788511, 98.982903, "POI text 2"]
];

var _overviewMarkerCoords = 
[
    [37.778716, -122.41994, "San Francisco, USA", "Pc7mWeY5bFZA", true, 
        ["Pier 39|BoGnWJZ8bFPA", "Jefferson St|MjGnWD96bFLF", "Maritime Park|XPGnWAm4bFHE", "Lombard st|3mEnW2f5bFiB", "The Embarcadero|ZgCnWdaDcFEF",
        "Broadway st|zWDnWPj9bFDF", "Filbert st|UaEnWnm8bFZE"],
        ["lombard st, sf", "bay st and powell st", "hotels near market st sf", "dining near pier 39"]
    ],
    
    [37.857197, -122.480988, "Sausalito, USA", "QkXnWEpjbF5F", true, 
        ["Bridgeway|nyWnWmPkbFnC"],
        ["571 bridgeway, sausalito", "johnson st and bonita st", "dining in sausalito"]
    ],

    [18.788522, 98.982559, "Chiang Mai, Thailand", "6fZyU2MbacZF", false, 
        ["Wat Phra Sing|6fZyU2MbacZF", "Three Kings Square|iGayUawcacQE", "Wat Mornthean|TpbyUmRbacUE", "Thanon Chang Lor|YUXyUS5ZaczF"],
        null
    ]
];

var _overviewMarkers = null;

// Page loaded, initiate application
function mapLoad()
{
    if (!GBrowserIsCompatible()) return;
    
    var startLon = -100.884619;   // Pattaya Beach Road 
    var startLat = 12.948574;
    
    var startMapType = 0;
    var startZoomLevel = 17;

    _map = new GMap2(document.getElementById("overviewMap"), {draggableCursor: 'hand', draggingCursor: 'hand'});
    _map.addControl(new GLargeMapControl());
    _map.addControl(new GScaleControl());
    _map.addControl(new GMapTypeControl());
    _map.addControl(new GOverviewMapControl());
    _map.setCenter(new GLatLng(startLat, startLon), startZoomLevel);
    if (startMapType == 0) _map.setMapType(G_HYBRID_MAP);
    else  _map.setMapType(G_NORMAL_MAP);
    _map.setCenter(new GLatLng(startLat, startLon), startZoomLevel);
    GEvent.addListener(_map, 'zoomend', zoomEndHandler);
    GEvent.addListener(_map, 'maptypechanged', updateDotOverlay);
    GEvent.addListener(_map, 'mousemove', mapMouseMove);
    GEvent.addListener(_map, 'click', userClick);


    // Avatar marker
    var avatarIcon = new GIcon();
    avatarIcon.image = "Images/Avatar0.gif";
    avatarIcon.iconSize = new GSize(18, 39);
    avatarIcon.iconAnchor = new GPoint(9, 34);
    avatarIcon.infoWindowAnchor = new GPoint(5, 1);
    for (var i = 0; i < 8; i++)
    {
        var image = new Image();
        image.src = "Images/Avatar" + i + ".gif";
        _avatarImages[_avatarImages.length] = image;
    }
    _avatar = new GMarker(new GLatLng(startLat, startLon), {icon:avatarIcon, draggable:true, bouncy:false, clickable:false});
    GEvent.addListener(_avatar, 'dragstart', avatarDragStartHandler);
    GEvent.addListener(_avatar, 'dragend', avatarDragEndHandler);
    _map.addOverlay(_avatar);
    
    // Beam drag marker
    var beamIcon = new GIcon();
    beamIcon.image = "Images/BeamDrag.gif";
    beamIcon.iconSize = new GSize(15, 15);
    beamIcon.iconAnchor = new GPoint(7, 7);
    beamIcon.dragCrossSize = new GSize(0, 0);
    _beamDrag = new GMarker(new GLatLng(startLat, startLon), {icon:beamIcon, draggable:true, bouncy:false, dragCrossMove:false});
    GEvent.addListener(_beamDrag, 'dragstart', beamDragStartHandler);
    GEvent.addListener(_beamDrag, 'drag', beamDragHandler);
    GEvent.addListener(_beamDrag, 'dragend', beamDragEndHandler);
    _map.addOverlay(_beamDrag);
    _beamDrag.hide();
    
    // POI markers
    for (var i = 0; i < _poiMarkers.length; i++)
    {
        var mIcon = new GIcon();
        mIcon.image = "Images/Marker.gif";
        mIcon.iconSize = new GSize(18, 28);
        mIcon.iconAnchor = new GPoint(9, 28);
        var marker = new GMarker(new GLatLng(_poiMarkers[i][0], _poiMarkers[i][1]), {icon:mIcon, title:_poiMarkers[i][2]});
        _map.addOverlay(marker);
    }
    
    // Add dot overlay and beam
    zoomEndHandler(null, null);
}

// Calls a function in any frame
function mapCall(name)
{
    var func = window[name];
    if (!func && parent)
    {
        for (var i = 0; i < parent.frames.length; i++)
        {
            func = parent.frames[i][name];
            if (func) break;
        }
    }
    if (func) return func(arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6]);
    else return null;    
}

function beamDragStartHandler()
{
    _isDraggingBeam = true;
}

function beamDragEndHandler()
{
    _beamDrag.hide();
    _isDraggingBeam = false;
}

function beamDragHandler()
{
    //var beamPos = _map.fromLatLngToDivPixel(_beamDrag.getPoint());
    //var beamPos = _map.fromLatLngToDivPixel(_mousePos);
    //var avatarPos = _map.fromLatLngToDivPixel(_avatar.getPoint());
    //var dragAng = 180 * Math.atan2(beamPos.x - avatarPos.x, avatarPos.y - beamPos.y) / Math.PI;
    //if (dragAng < 0) dragAng = 360 + dragAng;

    var beamPos = _beamDrag.getPoint();
    var avatarPos = _avatar.getPoint();
    var dragAng = 180 + 180 * Math.atan2(avatarPos.lng() - beamPos.lng(), avatarPos.lat() - beamPos.lat()) / Math.PI;

    _avatarHeading = dragAng;
    updateBeam();
    updateAvatar();
    
    mapCall("turnTo", _avatarHeading);
}

function mapMouseMove(pos)
{  
    if (_isDraggingBeam || _map.getZoom() <= 12) return;
    var avatarPos = _avatar.getPoint();
    _canDragMap = (avatarPos.distanceFrom(pos) > _beamDragDist)
    if (!_canDragMap)
    {
        _beamDrag.show();
        _beamDrag.setPoint(pos);
    }
    else
    {
        _beamDrag.hide();
    }
}

// Handles user clicks on the map
function userClick(marker, point) 
{
    if (marker) 
    {

        _map.openInfoWindowHtml(marker.getLatLng(), "zzz");

        //point = marker.getPoint();
        //window.open("http://www.netmobius.com");
        //alert("Click");
        //mapNavigateTo(point.lat(), point.lng());
        //if (_map.getZoom() < 14) _map.setZoom(14);
    }
    else 
    {
        mapNavigateTo(point.lat(), point.lng());
    }
}

function updateDotOverlay()
{
    var opacity = 1;
    var zoom = _map.getZoom();
    
    // Show city markers
    if (zoom < 10)
    {
        if (_overviewMarkers == null)
        {
            _overviewMarkers = new Array();
            var mIcon = new GIcon();
            mIcon.image = "Images/Marker.gif";
            mIcon.iconSize = new GSize(18, 28);
            mIcon.iconAnchor = new GPoint(9, 28);
            for (var i = 0; i < _overviewMarkerCoords.length; i++)
            {
                var marker = new GMarker(new GLatLng(_overviewMarkerCoords[i][0], _overviewMarkerCoords[i][1]), 
                    {icon:mIcon, title:_overviewMarkerCoords[i][2]});
                //GEvent.bind(marker, "click", this, userClick); 
                _map.addOverlay(marker);
                _overviewMarkers.push(marker);
            }
        }

    }
    else if (_overviewMarkers != null)
    {
        while (_overviewMarkers.length > 0) _map.removeOverlay(_overviewMarkers.pop());
        _overviewMarkers = null;
    }

    // Show dots
    if (zoom > 6)
    {
        
        if (_map.getCurrentMapType() == G_SATELLITE_MAP)
            opacity = _dotOpacityForSat[zoom - 1] / 10;
        else opacity = _dotOpacityForMap[zoom - 1] / 10;

        if (_dotOverlay != null) _map.removeOverlay(_dotOverlay);
        _dotLayer = new GTileLayer(new GCopyrightCollection(), 0, 17);
        _dotLayer.getTileUrl = function (a,b)
        {
            return "Dots/" + b + "/" + a.x + "/" +       
                b + "_" + a.x + "_" + a.y + ".gif";
        }
        _dotLayer.getOpacity = function (a) { return opacity; }
        _dotOverlay = new GTileLayerOverlay(_dotLayer);
        _map.addOverlay(_dotOverlay);
    }
    else if (_dotOverlay != null) _map.removeOverlay(_dotOverlay);
}

// Handles mouse drags of avatar
function zoomEndHandler(oldZoom, newZoom)
{
    updateDotOverlay();
    updateBeam();
    var avatarPos = _avatar.getPoint();
    var pixPos = _map.fromLatLngToDivPixel(avatarPos);
    var offsetPos = _map.fromDivPixelToLatLng(new GPoint(pixPos.x + _beamLength, pixPos.y));
    _beamDragDist = avatarPos.distanceFrom(offsetPos);
}

function showDots(show)
{
    if (!_dotOverlay) return false;
    if (show) _dotOverlay.show(); 
    else _dotOverlay.hide();
    return true;
}

function updateMap(lat, lon, heading, viewAngle)
{
    if (!_avatar || _isDraggingBeam) return false;

    _avatarLat = lat;
    _avatarLon = lon;
    _avatarHeading = heading;
    _beamAngle = viewAngle;
    
    updateAvatar();
    updateBeam();
    return true;
}

// Called by the panorama frame when position or heading has changed
function updateAvatar()
{
    if (!_avatar) return;
    var point = new GLatLng(_avatarLat, _avatarLon);
    _avatar.setPoint(point);
    _map.savePosition(point);
    _avatar.setImage(_avatarImages[Math.round(_avatarHeading / 45) % 8].src);
    panVisible(_avatar);
}

function updateBeam()
{
    if (!_avatar) return;

    var roundNess = parseInt(_beamAngle / 10);
    if (roundNess < 2) roundNess = 2;
    var center = _map.fromLatLngToDivPixel(_avatar.getPoint());
    var beamAngle = _beamAngle * Math.PI / 180;
    var heading = _avatarHeading * Math.PI / 180;
    var points = new Array();
    points[points.length] = _avatar.getPoint();
    for (var i = 0; i <= roundNess; i++)
    {
        var ang = heading + (beamAngle * i / roundNess) - (beamAngle / 2);
        var x = Math.sin(ang) * _beamLength;
        var y = -Math.cos(ang) * _beamLength;
        var p = _map.fromDivPixelToLatLng(new GPoint(x + center.x, y + center.y));
        points[points.length] = p;
    }
    points[points.length] = _avatar.getPoint();

    if (_beam) _map.removeOverlay(_beam);
    _beam = null;
    if (_map.getZoom() > 12)
    {
        _beam = new GPolygon(points, "#6666FF", 1, 1, "#AAAAFF", 0.5);
        _map.addOverlay(_beam);
    }
}

// Calls the panorama application to move to a coordinate
function mapNavigateTo(lat, lon)
{
    mapCall("navigateTo", lat, lon, true);
}

// Handles mouse drags of avatar
function avatarDragStartHandler()
{
    if (_beam) _map.removeOverlay(_beam);
    _beam = null;
}

// Handles mouse drags of avatar
function avatarDragEndHandler()
{
    var point = _avatar.getPoint();
    mapNavigateTo(point.lat(), point.lng());
}


// Makes sure a position is visible on the map
function panVisible(pos)
{
    var bounds = _map.getBounds();
    var size = bounds.toSpan();
    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    sw = new GLatLng(sw.lat() + size.lat()/10, sw.lng() + size.lng()/10);
    ne = new GLatLng(ne.lat() - size.lat()/10, ne.lng() - size.lng()/5);
    bounds = new GLatLngBounds(sw, ne);
    if (!bounds.contains(pos.getPoint()))
        _map.panTo(pos.getPoint());    
}

function addMarker(lat, lon, index)
{
    if (index >= 20) return;
    var mIcon = new GIcon();
    mIcon.image = "Images/Marker" + index + ".gif";
    mIcon.iconSize = new GSize(18, 28);
    mIcon.iconAnchor = new GPoint(9, 28);
    var marker = new GMarker(new GLatLng(lat, lon), {icon:mIcon});
    //GEvent.bind(marker, "click", this, function() 
    //{
    //});
    _map.addOverlay(marker);
    _markers.push(marker);
}

function removeMarkers()
{
    while (_markers.length > 0) _map.removeOverlay(_markers.pop());
}

