﻿$(document).ready(function () {
    $(".clearable").focus(function () {
        if (!$(this).hasClass(".focus")) {
            $(this).val("");
            $(this).addClass("focus");
        }
    });
    $(".search input.txt").keypress(function (e) {
        if (e.keyCode == 13) {
            window.location = "/search/" + $(this).parent().find("input.txt").val();
        }
    });
    $(".search input.btn").click(function () {
        window.location = "/search/" + $(this).parent().find("input.txt").val();
    });

    // toggle vis modules
    $("a.toggleVisBtn").click(function () {
        $($(this).attr("href")).toggle();
        return false;
    });

    // hover vis modules
    $("a.hoverVisBtn").hover(function () {
        $($(this).attr("href")).show();
    },
    function () {
        $($(this).attr("href")).hide();
    });

    $(".rating.disabled").hover(
        function () {
            ShowToolTipSimple("<p class='tooltipTxt'>Sign it at the top of this page to start rating trail conditions in your area!</p>");
        },
        function () {
            HideToolTip();
        }
    );

    // tabs
    $(".tabs .tab").click(function () {
        $(".tabs .tab").removeClass("selected");
        $(this).addClass("selected");
        $("#tabContents .tabContent").hide();

        $("#tabContents ." + $(this).attr("id")).show();
    });

    $(".discussion input:submit").click(function () {
        if ($(".discussion .city").val()) {
            alert("Your submission cannot be accepted.  Please try again.");
            return false;
        }

        var msg = $(".discussion textarea").val();

        $.post("/trail/message/", { trailId: TRAILS_TRAILID, message: msg }, function (success) {
            if (success) {
                window.location = window.location;
            } else {
                alert("An error has occurred.  Please try again.");
            }
        });

        return false;
    });
});

var SITE_ROOT = '/';
var maps = new Array();
var geoPositionWatcher;

$(window).load(function () {
    // custom, configured maps
    $(".googleMap:has(code)").each(function () {
        var map = new TrailMap($(this)[0], 0, $(this).find("code.latitude").text(), $(this).find("code.longitude").text(), parseInt($(this).find("code.zoom").text()), true, true);
        maps.push(map);
    });

    // single trail maps
    $("#trailMap").each(function () {
        var id = $(this).find('code').text();
        if (id != null) {
            var trailMap = new TrailMap($(this)[0], id, null, null, null, true, true);
            maps.push(trailMap);
        }
    });

    $(".mobileMap").each(function () {
        $(this).height($(window).height());

        $("a.findMe").click(function () {
            $(this).toggleClass("selected");

            if ($(this).hasClass("selected")) {
                maps[0].PanTo(currentLat, currentLng);
                geoPositionWatcher = navigator.geolocation.watchPosition(onWatchPosition);
            } else {
                navigator.geolocation.clearWatch(geoPositionWatcher);
                geoPositionWatcher = null;
            }
            return false;
        });

        window.addEventListener('orientationchange', function () {
            $(".mobileMap").width($(window).width());
        }, false);


        geoPositionWatcher = navigator.geolocation.watchPosition(onWatchPosition);
        defaultMobileMap();
        //setTimeout("checkForGeoAccess()", 2000);
    });
});

var currentLat;
var currentlng;

function onWatchPosition(position){
    followMap(position.coords.latitude, position.coords.longitude);
}

function followMap(latitude, longitude) {
    currentLat = latitude;
    currentLng = longitude;

    if (!maps || !maps.length) {
        var map = new TrailMap($(".mobileMap")[0], 0, latitude, longitude, 12, false, false);
        map.SetMarker(latitude, longitude);
        map.drawTrails();
        maps.push(map);
    } else {
        maps[0].SetMarker(latitude, longitude);
        // update marker position
        // also report on average speed and heading.
    }

    if ($("a.findMe").hasClass("selected")) {
        maps[0].PanTo(currentLat, currentLng);
    }
}

function defaultMobileMap()
{
    if(currentLat || currentlng) return;

    var map = new TrailMap($(".mobileMap")[0], 0, 46.732331, -94.669189, 6, false, false);
    map.SetMarker(latitude, longitude);
    map.drawTrails();
    maps.push(map);
}

var TrailMap = function (elem, id, lat, lng, zoom, allowTrailClicks, showZoom) {
    this.TrailID = id;
    this.SERVICE_URL = SITE_ROOT + "trailxml/mn/";
    this.firstLoad = true;
    this.requestID = "";
    var scope = this;
    this.overlays = new Array();
    this.boundsChangeListener = null;
    this.trailsURL;
    this.allowTrailClicks = allowTrailClicks;
    this.marker;

    this.OnMove = function () {
        //log("move.  zoomlevel: " + scope.Map.getBounds());
        //scope.drawTrails();
        scope.boundsChangeListener = google.maps.event.addListener(scope.Map, 'bounds_changed', scope.OnBounds);
    }

    this.OnZoom = function () {
        //log("zoom.  zoomlevel: " + scope.Map.getBounds());
        scope.boundsChangeListener = google.maps.event.addListener(scope.Map, 'bounds_changed', scope.OnBounds);
        scope.requestID = "";
        scope.ClearOverlays();
    }

    this.OnBounds = function () {
        //log(scope.overlays.length);
        if (scope.overlays.length > 500) {
            scope.ClearOverlays();
        }
        //log("bounds " + scope.zoomChangeListener);
        google.maps.event.removeListener(scope.boundsChangeListener);
        scope.drawTrails();
    }
    this.ClearOverlays = function () {
        for (var x = 0; x < scope.overlays.length; x++) {
            scope.overlays[x].setMap(null);
        }
        scope.overlays = new Array();
        scope.trailsURL = "";
        scope.requestID = "";
    }

    this.drawTrails = function () {
        var zoomLevel = scope.Map.getZoom();
        if (zoomLevel > 10 || scope.TrailID) {
            var sw = scope.Map.getBounds().getSouthWest();
            var ne = scope.Map.getBounds().getNorthEast();
            var tolerance = Math.abs(sw.lat() - ne.lat()) / 50;
            var url;

            if (scope.TrailID && zoomLevel <= 10) {
                url = scope.SERVICE_URL + scope.TrailID
            }
            else if (scope.TrailID) {
                url = scope.SERVICE_URL + scope.TrailID + "/" + tolerance + "/" + sw.lat() + "/" + sw.lng() + "/" + ne.lat() + "/" + ne.lng() + "/" + scope.requestID;
            } else {
                url = scope.SERVICE_URL + "0" + "/" + tolerance + "/" + sw.lat() + "/" + sw.lng() + "/" + ne.lat() + "/" + ne.lng() + "/" + scope.requestID;
            }
            if (scope.trailsURL != url) {
                scope.ajaxCall(url);
            }

            scope.trailsURL = url;
        }

        scope.Refresh();
    }

    this.ajaxCall = function (url) {
        $.ajax({ type: "GET", url: url, contentType: "text/xml", cache: false, dataType: "xml", async: true,
            success: function (xml) {
                if ($(xml).find("trails").find("trail").size()) {
                    scope.parseData(xml);
                }
            }
            //, error: function (a, b, c) { alert("error " + a + " | " + b + " | " + c); }
        });
    }

    this.parseData = function (xml) {
        HideToolTip();
        //log("parseData.  trails count: " + $(xml).find("trails").size());
        scope.requestID = $(xml).find("trails").attr("requestIdentifier");
        if (scope.TrailID && scope.firstLoad && $(xml).find("trail[selected='true']").size() > 0) {
            var trail = $(xml).find("trail[selected='true']");
            var sw = new google.maps.LatLng(trail.attr('minLat'), trail.attr('minLng'));
            var ne = new google.maps.LatLng(trail.attr('maxLat'), trail.attr('maxLng'));
            scope.Map.fitBounds(new google.maps.LatLngBounds(sw, ne));
        }
        else {
            $(xml).find('seg').each(function () {
                var prt = $(this).parent();
                scope.addTrailSegment($(this).attr('line'), prt.attr('selected'), prt.attr("id"), prt.attr("name"), prt.attr("url"), prt.attr("condition"))
            });
        }
        scope.firstLoad = false;
    }

    this.addTrailSegment = function (line, selected, trailId, trailName, url, condition) {
        var linePoints = decodeLine(line);
        var points = new Array();
        for (var x = 0; x < linePoints.length; x++) {
            points.push(new google.maps.LatLng(linePoints[x][0], linePoints[x][1]));
        }
        var stroke = selected ? "#4F5E6E" : "#E87543";
        var opacity = selected ? 1 : .8;
        var line = new google.maps.Polyline({ path: points, strokeColor: stroke, strokeWeight: 4, strokeOpacity: opacity, trailId: trailId, url: url, line: line });
        google.maps.event.addListener(line, 'mouseover', scope.SegmentMouseOver);
        google.maps.event.addListener(line, 'mouseout', scope.SegmentMouseOut);

        if (this.allowTrailClicks) {
            google.maps.event.addListener(line, 'click', function () { window.location = "http://www.etrailfinder.com/" + this.url });
        }

        line.setMap(scope.Map);
        scope.overlays.push(line);
    }

    this.SegmentMouseOver = function (e) {
        ShowToolTip("/us/mn/summary/" + this.trailId, mouseX + 10, mouseY + 10);
    }
    this.SegmentMouseOut = function (e) {
        HideToolTip();
    }
    this.Refresh = function () {
        UpdateTrailList(scope.Map.getBounds(), scope.TrailID);
    }

    this.SetMarker = function (lat, lng) {
        if (!scope.marker) {
            scope.marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lng), title: "Your current position" });
            scope.marker.setAnimation(google.maps.Animation.DROP);
            scope.marker.setMap(this.Map);
        } else {
            scope.marker.setMap(null);
            scope.marker = new google.maps.Marker({ position: new google.maps.LatLng(lat, lng), title: "Your current position" });
            scope.marker.setMap(this.Map);
        }
    }

    this.PanTo = function (lat, lng) {
        this.Map.panTo(new google.maps.LatLng(lat, lng));
    }

    this.Map = new google.maps.Map(elem, { zoom: zoom != null ? zoom : 6, mapTypeId: google.maps.MapTypeId.TERRAIN, streetViewControl: false, zoomControl: showZoom });
    google.maps.event.addListener(this.Map, 'dragend', this.OnMove);
    google.maps.event.addListener(this.Map, 'zoom_changed', this.OnZoom);

    var trailTilesMapType = new google.maps.ImageMapType({
        getTileUrl: function (coord, zoom) {
            if (zoom <= 10) {
                return '/images/mapTiles/x' + coord.x + 'y' + coord.y + 'z' + zoom + '.png';
            }
        },
        tileSize: new google.maps.Size(256, 256),
        inPng: true
    });
    this.Map.overlayMapTypes.insertAt(0, trailTilesMapType);

    if (this.TrailID) {
        this.ajaxCall(scope.SERVICE_URL + scope.TrailID);
    } else {
        this.Map.setCenter(new google.maps.LatLng(lat, lng));
    }
}

var updateCallOut = false;
// Show local trails method
function UpdateTrailList(bounds, trailID) {
    if ($("#trailsList").size() == 0)
        return;

    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var url = "/us/mn/list/" + sw.lat() + "/" + sw.lng() + "/" + ne.lat() + "/" + ne.lng();

    if (trailID != null) url += "/" + trailID;

    if (!updateCallOut) {
        updateCallOut = true;
        $.ajax({ url: url, dataType: "html", async: true,
            success: function (html) { $("#trailsList").html(html); updateCallOut = false; },
            error: function (html) { updateCallOut = false; }
        });
    }
}

// Tooltip methods
var tooltipShown = false;
function ShowToolTip(url, x, y) {
    if (tooltipShown) return;
    tooltipShown = true;
    var scope = this;
    this.OnLoad = function (html) {
        if (!tooltipShown) return;
        if ($("#tooltip").size() == 0) {
            $("body").append("<div id=\"tooltip\"></div>");
        }
        $("#tooltip").hide().html(html).css("top", y).css("left", x).show();
    }

    $.ajax({ type: "GET", url: url, dataType: "html", async: true, cache: false,
            success: function (html) { scope.OnLoad(html); }});
}

function ShowToolTipSimple(html) {
    if ($("#tooltip").size() == 0) {
        $("body").append("<div id=\"tooltip\"></div>");
    }
    $("#tooltip").hide().html(html).css("top", mouseY).css("left", mouseX).show();
}

function HideToolTip() {
    tooltipShown = false;
    $("#tooltip").hide();
}

// - helper methods - //
// track the mouse (useful for tooltips)
var mouseX = 0
var mouseY = 0;
$(document).ready(function () {
    $(document).mousemove(function (e) {
        mouseX = e.pageX;
        mouseY = e.pageY;
    });
});

// decode polylines
function decodeLine(encoded) {
    encoded = encoded.replace(/\\\\/g, "\\");
    var len = encoded.length;
    var index = 0;
    var array = [];
    var lat = 0;
    var lng = 0;

    while (index < len) {
        var b;
        var shift = 0;
        var result = 0;
        do {
            b = encoded.charCodeAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        var dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lat += dlat;

        shift = 0;
        result = 0;
        do {
            b = encoded.charCodeAt(index++) - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);
        var dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lng += dlng;

        array.push([lat * 1e-5, lng * 1e-5]);
    }

    return array;
}
