var MAPS = [
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23509&destination=23509&sensor=false
    {
        "index":0,
        "zipCode":23509,
        "url":'/serving-area-norfolk-virginia',
        "lat":36.8836300,
        "long":-76.2514500,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23704&destination=23704&sensor=false
    {
        "index":1,
        "zipCode":23704,
        "url":'/serving-area-chesapeake-virginia',
        "lat":36.8288800,
        "long":-76.3149200,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23321&destination=23321&sensor=false
    {
        "index":2,
        "zipCode":23321,
        "url":'/serving-area-suffolk-virginia',
        "lat":36.8106000,
        "long":-76.4140700,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23707&destination=23707&sensor=false
    {
        "index":3,
        "zipCode":23707,
        "url":'/serving-area-portsmouth-virginia',
        "lat":36.8420400,
        "long":-76.3361700,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23452&destination=23452&sensor=false
    {
        "index":4,
        "zipCode":23452,
        "url":'/serving-area-virginia-beach-virginia',
        "lat":36.8489100,
        "long":-76.0973700,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23606&destination=23606&sensor=false
	{
        "index":5,
        "zipCode":23606,
        "url":'/serving-area-newport-news-virginia',
        "lat":37.0513800,
        "long":-76.5046300,
        "distance":0
    },	
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23669&destination=23669&sensor=false
	{
        "index":6,
        "zipCode":23669,
        "url":'/serving-area-hampton-virginia',
        "lat":37.0024700,
        "long":-76.3840900,
        "distance":0
    },	
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23603&destination=23603&sensor=false
	{
        "index":7,
        "zipCode":23603,
        "url":'/serving-area-williamsburg-virginia',
        "lat":37.2259400,
        "long":-76.5881900,
        "distance":0
    },
	//http://maps.googleapis.com/maps/api/directions/xml?origin=23225&destination=23225&sensor=false
	{
        "index":8,
        "zipCode":23225,
        "url":'/serving-area-richmond-virginia',
        "lat":37.5179600,
        "long":-77.4933300,
        "distance":0
    }	
];

var JID = 
{
    'submitButton':'#btnLocate',
    'originLocation':'#txtLocation',
	'searchIndicator':'#imgSearchIndicator'
};

var COUNT_MAPS = MAPS.length;
var MAX_DISTANCE = 999999999999;

// SEE:  http://code.google.com/apis/maps/documentation/directions/
var BASE_MAPPING_SERVICE_URL = 'http://www.minipricestorage.com/google-maps-web-service-proxy?';
// 'http://174.121.161.226/~minipric'
var BASE_MAP_URL = 'http://www.minipricestorage.com';

var resultText = "";

function isInteger(n)
{
    return (!isNaN(parseInt(n)) && isFinite(n));
}

function isValidUSZIPCode(testValue)
{
	var isValidUSZIPCode = false;
	
	if (testValue != null)	
	{
		isValidUSZIPCode = /^\d{5}(-\d{4})?$/.test(testValue);		
	}
	
	return isValidUSZIPCode;	
}

// Purpose:  Converts an angle in degrees to radians.
function convertToRadians(angle)
{
	return (angle * (Math.PI / 180));	
}

// Purpose:  Uses the Haversine formula to computer the distance between two decimal-formatted latitude,longitude points on a sphere.
function calculateDistanceBetweenTwoMapPoints(latPoint1, longPoint1, latPoint2, longPoint2)
{
	//Mean radius of the Earth in km
	var radiusOfEarth = 6371; 
	
	var deltaLat = convertToRadians(latPoint2 - latPoint1);
	var sin2DeltaLatHalfAngle = Math.pow(Math.sin((deltaLat / 2)), 2);
	
	var deltaLong = convertToRadians(longPoint2 - longPoint1);
	var sin2DeltaLongHalfAngle = Math.pow(Math.sin((deltaLong / 2)), 2);
	
	var a = sin2DeltaLatHalfAngle + Math.cos(convertToRadians(latPoint1)) * Math.cos(convertToRadians(latPoint2)) * sin2DeltaLongHalfAngle;
	
	var c = 2 * Math.atan(Math.sqrt(a), Math.sqrt(1 - a));
	
	// distance is the distance between the two points (along a great circle of the sphere).
	var distance = (radiusOfEarth * c);
	
	return distance;	
}

// Purpose:  Calculates the distance to each of the pre-defined maps from a specified origin point lat, long pair.
function identifyClosestMapByIndex(originLat, originLong)
{
	// Reset the map distance calculation variables.
    var mapIndexWithShortestDistance = -1;
    
	// The current, shortest distance from origin map point to the defined map coordinate point.
    var currentShortestDistance = MAX_DISTANCE;
	
	if ((isNaN(originLat) == false) && (isNaN(originLong) == false)) 
	{		
		for (var i = 0; i < COUNT_MAPS; i++) 
		{			
			MAPS[i].distance = calculateDistanceBetweenTwoMapPoints(originLat, originLong, MAPS[i].lat, MAPS[i].long);
							
			if (MAPS[i].distance < currentShortestDistance) 
			{
				mapIndexWithShortestDistance = i;
				currentShortestDistance = MAPS[i].distance;
			}
			
			//resultText += ("\nDistance from origin to MAP " + i + ":  " + MAPS[i].distance + " (km). MAP " + mapIndexWithShortestDistance + " is closest so far.");
		}			
	}
    
	$(JID.searchIndicator).hide();
	
    if ((mapIndexWithShortestDistance > -1) && (mapIndexWithShortestDistance < COUNT_MAPS))
	{
		var mapURL = (BASE_MAP_URL + MAPS[mapIndexWithShortestDistance].url);
		
		//alert("Mapping Service URL:  " + mappingServiceURL + "\n\nOrigin Location (lat,lng):  (" + originLat + ", " + originLong + ")" + resultText + "\n\nMap Index with Shortest Distance:  " + mapIndexWithShortestDistance + "\n\nMap URL:  " + mapURL);
		
        window.location.href = (mapURL);
    }
    else 
    {
        alert("Unfortunately, the closest MiniPrice Storage facility could not be located.  Please check that the starting search address exists and is formatted properly.");
    }  	
}

// Purpose:  Calculates the map URL for the closest store based on an entered origin location.
function findClosestStore()
{   
    // Retrieve the origin ZIP Code from the text field.
    var originLocation = jQuery.trim($(JID.originLocation).val());
    
    // Proceed if the originZIPCode is non-null and has a 5 digit character length and is a valid integer.
    if ((originLocation != null) && (originLocation.length > 0)) 
    {
     	// Determine if only a valid ZIP code was entered.
	 	// Examine the originLocation for the presence of a comma that would denote a state value.
		if ((isValidUSZIPCode(originLocation) == false) && (originLocation.indexOf(',') <= -1))		
		{
			// It is probable that a state value was not included, so append a ",VA" text suffix.
			originLocation += (',VA');
		}
		
		$(JID.searchIndicator).show();
		
		var mappingServiceURL = BASE_MAPPING_SERVICE_URL + 'origin=' + encodeURIComponent(originLocation) + '&dest=' + encodeURIComponent(originLocation);
		
		var originLat = Number.NaN;
		var originLong = Number.NaN;
		
		// Retreive the distance from the origin ZIP code to each of the map ZIP codes
        // using the Google Maps Web Service.
        $.ajax(
            {
                url: mappingServiceURL,
                dataType: 'xml',
                success: function(data, textStatus, xhr)
                {
                    // The <DirectionsResponse> should return a status of "OK".
                    var _status = $(data).find("status:first");
                    
                    if ((_status != null) && (_status.text() == 'OK'))                    
					{
						var _startLocation = $(data).find("leg:first > start_location:first");
							
						if (_startLocation != null)
						{
	                        var _lat = _startLocation.find("lat:first");
							var _long = _startLocation.find("lng:first");
							
							if (_lat != null)							
							{
								originLat = parseFloat(_lat.text());
							}					
							
							if (_long != null)
							{
								originLong = parseFloat(_long.text());
							}				
						}
						
						identifyClosestMapByIndex(originLat, originLong)
                    }
                },
                error: function(xhr, textStatus, errorThrown)
                {
                    mapIndexWithShortestDistance = -1;
                }
        });		      
    }
    else 
    {
        alert("You must enter an origin location to check for the nearest MiniPrice Storage facility.");
    }    
}

$(window).load(function()
{
    $(JID.submitButton).click(function()
    {
        findClosestStore();
    });
});
