﻿
/// <reference path="jquery-1.3.1-vsdoc.js"/>

var map = null;
var bounds = null;
var markerClusterer = null;
var markersArr = [];
var storeResults = "";
var KMPERMILE = 1.609344;
var mapMoveEndListener = null;

function initialize()
{
    // fixes issues with IE6 and PNG images
    DD_belatedPNG.fix("img[@src$=png]");

    $("#btnSearch").click(function() { geocodeAddress($("#txtCityStateZip").val()); });

    $("#txtCityStateZip").keydown(function(e) { if (e.keyCode == 13) { geocodeAddress($("#txtCityStateZip").val()); } });
    $("#txtCityStateZip").focus();

    map = new GMap2(document.getElementById('map_canvas'));

    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());

    map.setCenter(new GLatLng(38.41055825094609, -95.80078125));
    map.setZoom(3);

    GEvent.addListener(map, "click", mapClick);
    mapMoveEndListener = GEvent.addListener(map, "moveend", mapMoveend);
    GEvent.addListener(map, 'extinfowindowupdate', function() { $("#txtStartAddress").val(currentAddress); });

    mapResturants("");
}

/*
function initMapClickEventListener()
{
    mapClickEventListener = GEvent.bind(map, "click", this, function(overlay, latlng, overlaylotlng)
    {
        if (overlaylatlng != null) // if the user clicked on an overlay
        {
            // remove listener
            GEvent.removeListener(mapClickEventListener);
            // pan map
            map.panTo(overlaylatlng);
            // after 1 second, add the listener back
            setTimeout(function() { initMapClickEventListener(); }, 1000);
        }
    });
}
*/

function mapClick(overlay, latlng, overlaylatlng)
{
    if (overlaylatlng != null)
    {
        GEvent.removeListener(mapMoveEndListener);
        map.panTo(overlaylatlng);
        setTimeout(function() { mapMoveEndListener = GEvent.addListener(map, "moveend", mapMoveend); }, 1500);
    }
}

function mapMoveend()
{
    map.closeExtInfoWindow();
}

function removeOverlays()
{
    var numberOfOverlays = radiusOverlay.length;
    var i = 0;
    do
    {
        if (radiusOverlay[i] != null)
        {
            map.removeOverlay(radiusOverlay[i]);
            radiusOverlay[i] = null;
        }
        i++;
    }
    while (i < numberOfOverlays);
}

function geocodeAlternateAddress(query)
{
    currentQuery = query;
    removeOverlays();
    var geocoder = new GClientGeocoder();
    geocoder.getLocations(query, geocodeAddressResult);
}

var currentQuery = "";
function geocodeAddress(query)
{
    currentQuery = query;

    if (query.toString().length == 2)
        query = query.toString().toUpperCase() + ", USA";

    currentOtherResults = "";
    removeOverlays();    
    var geocoder = new GClientGeocoder();
    geocoder.getLocations(query, geocodeAddressResult);
}

var currentAddress = "";
var currentOtherResults = "";
var lastSearchWasAddress = false;
var lastPlacemarkLength = 0;
function geocodeAddressResult(result)
{
    map.closeExtInfoWindow();

    if (result.Status.code == 200)
    {
        var placemark = result.Placemark[0];
        var accuracy = placemark.AddressDetails.Accuracy;
        var origin = new GLatLng(placemark.Point.coordinates[1], placemark.Point.coordinates[0]);

        if (placemark.AddressDetails.Country.CountryNameCode != "US")
        {
            $("#storeResults").html("Location was outside the United States: <br/><br/>" + placemark.address.replace(",", "<br/>"));
            return;
        }

        if (accuracy < 6) // less than address level
        {
            lastSearchWasAddress = false;

            if (accuracy == 5) // zip code level
            {
                lastSearchWasAddress = true;
                currentAddress = placemark.address;

                findClosestStoreToZip(currentQuery);
            }
            else
            {
                zoomToResturants(currentQuery);
            }
        }
        else // address level or better match
        {
            lastSearchWasAddress = true;
            currentAddress = placemark.address;

            placeRadiusLayerOnMap(origin, 1 * KMPERMILE, 0);
            var bounds = placeRadiusLayerOnMap(origin, 3 * KMPERMILE, 1);

            map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

            $("#storeResults").html("Resturants within 1 and 3 miles from: <br/><br/>" + currentAddress.replace(",", "<br/>") + "");
            $("#storeResults").append(currentOtherResults);
        }

        // if more than one address accuracy match, create a link list
        if (accuracy >= 6 && result.Placemark.length > 1)
        {
            var otherResults = "<br/><br/><br/><strong>All address matches:</strong><br/><br/>";

            for (var i = 0; i < result.Placemark.length; i++)
            {
                if (currentAddress != result.Placemark[i].address)
                {
                    otherResults +=
                        "<a class='otherResults' href='javascript: geocodeAlternateAddress(\"" + escape(result.Placemark[i].address) + "\");'>" +
                        result.Placemark[i].address.replace(",", "<br/>") +
                        "</a><br/><br/>";
                }
                else
                {
                    otherResults +=
                        "<strong><a class='otherResults' href='javascript: geocodeAlternateAddress(\"" + escape(result.Placemark[i].address) + "\");'>" +
                        result.Placemark[i].address.replace(",", "<br/>") +
                        "</a></strong><br /><br />";
                }
            }

            currentOtherResults = otherResults;
            $("#storeResults").append(currentOtherResults);
        }
    }
    else
    {
        $("#storeResults").html("Unable to find location on map");
    }
}

var radiusOverlay = new Array(2);
function placeRadiusLayerOnMap(origin, radius, idx) 
{
	//calculating km/degree
    var latConv = origin.distanceFrom(new GLatLng(origin.lat() + 0.1, origin.lng())) / 100;
    var lngConv = origin.distanceFrom(new GLatLng(origin.lat(), origin.lng() + 0.1)) / 100;

	var bounds = new GLatLngBounds();
	var points = [];
	var step = 5; // 360/step = number of points in polygon
	
	for(var i=0; i<=360; i+=step)
	{
	    var pint = new GLatLng(origin.lat() + (radius / latConv * Math.cos(i * Math.PI / 180)), origin.lng() + (radius / lngConv * Math.sin(i * Math.PI / 180)));
	    points.push(pint);
	    bounds.extend(pint);
	}

	points.push(points[0]); 
	
	radiusOverlay[idx] = new GPolygon(points, "#0055FF", 0.1, 0, "#0055FF", 0.1);
	map.addOverlay(radiusOverlay[idx]);

	return bounds;
}


function zoomToResturants(query)
{
    if (GBrowserIsCompatible())
    {
        $("#loading").css("display", "block");

        $.get("storelocator_service.aspx", { q: query },
            function(xml) {
                var rowCount = parseInt($("rowCount", xml).text());
                var queryType = $("queryType", xml).text();

                if (rowCount > 0) {
                    markersArr = [];
                    storeResults = "";

                    $("restaurant", xml).each(function() {
                        var xmlNode = $(this);

                        var lat = parseFloat(xmlNode.find("lat").text());
                        var lon = parseFloat(xmlNode.find("lon").text());

                        var marker = new GMarker(new GLatLng(lat, lon));
                        markersArr.push(marker);

                    });

                    var bounds = new GLatLngBounds();
                    for (i = 0; i < markersArr.length; i++) {
                        bounds.extend(markersArr[i].getLatLng());
                    }

                    map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

                }

                $("#storeResults").html("");

                if (query.length > 0) {
                    if (rowCount > 0) {
                        var suffix = "";

                        switch (queryType) {
                            case "State":
                                suffix = "for " + query.toUpperCase();
                                break;
                            case "Zip":
                                suffix = "with a " + query + " zip code"
                                break;
                            default:
                                suffix = "for " + query;
                        }

                        $("#storeResults").append(rowCount + " resturant" + ((rowCount > 1) ? "s" : "") + " found " + suffix + "<br /><br />" + storeResults);
                    }
                    else {
                        $("#storeResults").html("No resturants were found");
                    }
                }
                else {
                    $("#storeResults").html("Examples: <br /><br />Oklahoma City, OK<br />TX<br />72501<br/>4441 S 72nd E Ave, Tulsa, OK");
                }

                $("#loading").css("display", "none");
            }
        );
    }
}


function mapResturants(query)
{
    if (GBrowserIsCompatible())
    {
        $("#loading").css("display", "block");

        $.get("storelocator_service.aspx", { q: query },
            function(xml)
            {
                var rowCount = parseInt($("rowCount", xml).text());
                if (rowCount > 0)
                {
                    if (markerClusterer != null)
                        markerClusterer.removeMarkers();

                    map.clearOverlays();

                    markersArr = [];
                    storeResults = "";

                    $("restaurant", xml).each(function()
                    {
                        var xmlNode = $(this);

                        var id = xmlNode.find("id").text();
                        var lat = parseFloat(xmlNode.find("lat").text());
                        var lon = parseFloat(xmlNode.find("lon").text());
                        var address = xmlNode.find("address").text();
                        var phone = xmlNode.find("phone").text();
                        var hours = xmlNode.find("hours").text();
                        var delivery = xmlNode.find("delivery").text();
                        var carryout = xmlNode.find("carryout").text();
                        var dinein = xmlNode.find("dinein").text();
                        var freewifi = xmlNode.find("freewifi").text();

                        var icon = new GIcon();
                        icon.image = 'images/mapiconsingle.png';
                        icon.iconSize = new GSize(42, 42);
                        icon.iconAnchor = new GPoint(21, 21);
                        icon.infoWindowAnchor = new GPoint(21, 10);

                        var marker = new GMarker(new GLatLng(lat, lon), icon);
                        GEvent.addListener(marker, 'click', function()
                        {
                            setTimeout(function()
                            {
                                marker.openExtInfoWindow(map, "infoWindow",
                                    "<div style='text-align:center; width:100%'>Loading restaurant info...</div>",
                                    { ajaxUrl: "storelocator_service.aspx?info=" + id, beakOffset: 6 });
                            }, 1);
                        });

                        markersArr.push(marker);

                        storeResults +=
                            address + "<br />" +
                            phone + "<br />" +
                            ((delivery == "True") ? "Del " : "") +
                            ((carryout == "True") ? "CO " : "") +
                            ((dinein == "True") ? "DI " : "") +
                            ((freewifi == "True") ? "WiFi " : "") +
                            "<br /><br />";
                    });

                    markerClusterer = new ClusterMarker(map, { markers: markersArr, clusterMarkerTitle: "Click here to see resturants in this area" });
                    markerClusterer.fitMapToMarkers();
                    markerClusterer.refresh(true);

                }

                $("#storeResults").html("");

                if (query.length > 0)
                {
                    if (rowCount > 0)
                    {
                        $("#storeResults").append("Resturants found: " + rowCount + "<br /><br />" + storeResults);
                    }
                    else
                    {
                        $("#storeResults").append("No resturants were found");
                    }
                }
                else
                {
                    $("#storeResults").html("Examples: <br /><br />Oklahoma City, OK<br />TX<br />72501<br/>4441 S 72nd E Ave, Tulsa, OK");
                }

                $("#loading").css("display", "none");
            }
        );
    }
}

function directions(startAddress, endAddress)
{
    if (startAddress.toString().length > 0)
    {
        window.open("http://maps.google.com/maps?q=from:+" + startAddress + "+to:+" + endAddress, "DrivingDirections", null, null);
    }
    else
    {
        alert("Please enter a starting address");
    }
}

var currentZip = "";
function findClosestStoreToZip(zip)
{
    currentZip = zip;
    var geocoder = new GClientGeocoder();
    geocoder.getLatLng(zip, findClosestStoreToZipResult);
}

function findClosestStoreToZipResult(origin)
{
    if (origin != null)
    {
        // get zip center point lat/lng
        // get the distance to every other location's lat/lng
        // if any location is < 10 miles away, put a radius overlay at 5 & 10 miles like an address search at zip center
        // else create a radius overlay just big enough to encompass the closest location

        var minimumKmFromZip = 3 * KMPERMILE;
        var closestLocAndDistance = null;

        for (var i = 0; i < markersArr.length; i++)
        {
            var location = markersArr[i].getLatLng();
            var distance = (origin.distanceFrom(location) * 0.001).toFixed(5); // distanceFrom returns meters

            if (parseFloat(distance) <= parseFloat(minimumKmFromZip))
            {
                // loc found in radius
                placeRadiusLayerOnMap(origin, 1 * KMPERMILE, 0);
                var bounds = placeRadiusLayerOnMap(origin, 3 * KMPERMILE, 1);
                map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
                $("#storeResults").html("Resturants within 1 and 3 miles from the center of: <br/><br/>" + currentAddress + "");

                return;
            }
            else
            {
                if (closestLocAndDistance != null)
                {
                    if (parseFloat(distance) < parseFloat(closestLocAndDistance[1]))
                        closestLocAndDistance = new Array(location, parseFloat(distance));
                }
                else
                {
                    closestLocAndDistance = new Array(location, parseFloat(distance));
                }
            }
        }

        var bounds = placeRadiusLayerOnMap(origin, closestLocAndDistance[1], 0);
        map.setCenter(origin , map.getBoundsZoomLevel(bounds));
        $("#storeResults").html("Closest resturant is approximately " + Math.round(closestLocAndDistance[1] / KMPERMILE) + " miles from the center of: <br/><br/>" + currentAddress + "");

        return;
    }    
}