﻿LocationMap = (function() {
    var _map = null; // the map object to use
    var _directions = null; // GDirections object
    var _geocoder = null;
    var _murphyIcon = null;

    var baseIcon = new google.maps.Icon();
    baseIcon.iconSize = new google.maps.Size(17, 17);
    baseIcon.iconAnchor = new google.maps.Point(8, 8);
    baseIcon.infoWindowAnchor = new google.maps.Point(10, 0);

    var _destInput = null; // the destination input
    var _srcInput = null; // teh source input
    var _radiusInput = null; // the radius input
    var _storeList = null;

    var _addr = {};


    function onDirectionsErrors() {
        var gdir = _directions;
        if (gdir.getStatus().code == G_GEO_UNKNOWN_ADDRESS)
            alert("No corresponding geographic location could be found for one of the specified addresses. This may be due to the fact that the address is relatively new, or it may be incorrect.\nError code: " + gdir.getStatus().code);
        else if (gdir.getStatus().code == G_GEO_SERVER_ERROR)
            alert("A geocoding or directions request could not be successfully processed, yet the exact reason for the failure is not known.\n Error code: " + gdir.getStatus().code);
        else if (gdir.getStatus().code == G_GEO_MISSING_QUERY)
            alert("The HTTP q parameter was either missing or had no value. For geocoder requests, this means that an empty address was specified as input. For directions requests, this means that no query was specified in the input.\n Error code: " + gdir.getStatus().code);
        //   else if (gdir.getStatus().code == G_UNAVAILABLE_ADDRESS)  <--- Doc bug... this is either not defined, or Doc is wrong
        //     alert("The geocode for the given address or the route for the given directions query cannot be returned due to legal or contractual reasons.\n Error code: " + gdir.getStatus().code);
        else if (gdir.getStatus().code == G_GEO_BAD_KEY)
            alert("The given key is either invalid or does not match the domain for which it was given. \n Error code: " + gdir.getStatus().code);
        else if (gdir.getStatus().code == G_GEO_BAD_REQUEST)
            alert("A directions request could not be successfully parsed.\n Error code: " + gdir.getStatus().code);
        else alert("An unknown error occurred.");
    }

    function onDirectionsLoad() {
        if (LocationMap.LocationsPOI) {
            var pLine = _directions.getPolyline();
            var l = pLine.getLength() / 1609, r = getRadius();
            var i, v = pLine.getVertexCount();
            var radius = Math.max((l > 500 ? 20 : (l > 250 ? 10 : 5)), r) * 1609;
            var threshhold = radius * .7;
            var path = [];
            var lastPoint = new GLatLng(0, 0);
            for (i = 0; i < v; i++) {
                var p = pLine.getVertex(i);
                if (p.distanceFrom(lastPoint) > threshhold) {
                    path.push(p.toUrlValue(3));
                    lastPoint = p;
                }
            }
            LocationMap.LocationsPOI(radius / 1609, path.join('x'), setMarkers);
        }
    }

    function onMapClick(overlay, latlng) {
        if (latlng != null) {
            _map.clearOverlays();
            _storeList.innerHTML = '';
            _geocoder.getLocations(latlng, showAddress);
        }
    }

    function createStoreMarker(latlng, storeObj) {
        var d = document.createElement('div');
        d.innerHTML = storeObj.Formated;
        var store = d.removeChild(d.firstChild);
        _storeList.appendChild(store);
        var marker = new google.maps.Marker(latlng, { title: storeToString(storeObj), icon: _murphyIcon, clickable: typeof LocationMap.LocationDetail == 'function' });
        if (LocationMap.LocationDetail) {
            google.maps.Event.addListener(marker, 'click', function() {
                LocationMap.LocationDetail(storeObj.StoreNum, storeObj.DistanceFromSearch || 0, function(result) {
                    marker.openInfoWindow(result);
                });
            });
            store.style.cursor = 'pointer';
            store.onclick =  function() {
                LocationMap.LocationDetail(storeObj.StoreNum, storeObj.DistanceFromSearch || 0, function(result) {
                    marker.openInfoWindow(result);
                });
            };
        }
        return marker;
    }

    function setDefaultLocation() {
        if (LocationMap.initDest && _destInput) {
            _destInput.value = LocationMap.initDest;
        }
        if (LocationMap.initRadius) {
            setRadius(LocationMap.initRadius);
        }
        if (google.loader.ClientLocation && google.loader.ClientLocation.address &&
			google.loader.ClientLocation.address.country_code == "US") {
            ctr = new google.maps.LatLng(google.loader.ClientLocation.latitude, google.loader.ClientLocation.longitude);
            _map.setCenter(ctr, 5);
            if (!LocationMap.initLoc) {
                LocationMap.initLoc = google.loader.ClientLocation.address.region.toUpperCase();
            }
        }
        else {
            _map.setCenter(new google.maps.LatLng(33.213521, -92.662553), 5);
            if (!LocationMap.initLoc) {
                setRadius(0);
                LocationMap.initLoc = 'El Dorado, AR';
            }
        }
        if (LocationMap.initLoc && _srcInput) {
            _srcInput.value = LocationMap.initLoc;
        }
        LocationMap.searchMap();
    }

    function showAddress(response) {
        if (!response || response.Status.code != 200) {
            alert("Status Code:" + response.Status.code);
        } else {
            var place = response.Placemark[0];
            _addr = {};
            _addr.name = response.name.replace(', USA', '');
            _addr.point = new google.maps.LatLng(place.Point.coordinates[1], place.Point.coordinates[0]);
            _addr.address = place.address;
            _addr.country = place.AddressDetails.Country.CountryNameCode;
            _addr.state = place.AddressDetails.Country.AdministrativeArea.AdministrativeAreaName;
            _srcInput.value = _addr.address;

            showSearch();
        }
    }

    function setMarkers(result) {
        if (result != null && result.length > 0) {
            var bounds = new google.maps.LatLngBounds();
            var i, l = result.length;

            for (i = 0; i < l; i++) {
                var r = result[i];
                var latlng = new google.maps.LatLng(r.Lat, r.Long);
                bounds.extend(latlng);
                var marker = createStoreMarker(latlng, r);
                _map.addOverlay(marker);
            }
            _map.panTo(bounds.getCenter());
            //_map.setZoom(_map.getBoundsZoomLevel(bounds));
        }
        else {
            alert('No locations found for ' + _addr.name + (getRadius() > 0 ? ' within ' + getRadius() + ' miles!' : '!') + '\nActual address searched was: ' + _addr.address);
        }
    }

    function showSearch() {
        var radius = getRadius();
        if (radius && LocationMap.LocationsInRadius) {
            LocationMap.LocationsInRadius(radius, _addr.point.lat(), _addr.point.lng(), setMarkers);
        }
        else {
            LocationMap.LocationsIn(_addr.state, setMarkers);
        }
    }

    function getRadius() {
        if (_radiusInput == null) {
            return 0;
        }
        return parseInt(_radiusInput.options[_radiusInput.selectedIndex].value, 10);
    }
    function setRadius(value) {
        if (_radiusInput == null) return;
        for (var i = _radiusInput.options.length - 1; i >= 0; i--) {
            if (_radiusInput.options[i].value == value)
                _radiusInput.selectedIndex = i;
        }
    }

    function storeToString(store) {
        return [store.Address, ' - ', store.Phone, ': ', store.City, ', ', store.State].join('');
    }

    return {
        init: function() {
            _geocoder = new google.maps.ClientGeocoder();
            _srcInput = document.getElementById(LocationMap.ToFieldId);
            _destInput = document.getElementById(LocationMap.FromFieldId);
            _radiusInput = document.getElementById(LocationMap.RadiusFieldId);
            _storeList = document.getElementById(LocationMap.ListElId);

            _murphyIcon = new google.maps.Icon(baseIcon);
            _murphyIcon.image = 'http://murphyusa.com/!img/common/murphyoil_icon_stars.png';


            _map = new google.maps.Map2(document.getElementById(LocationMap.MapContId));
            _map.setUIToDefault();

            google.maps.Event.addListener(_map, "click", onMapClick);



            _directions = new google.maps.Directions(_map, document.getElementById(LocationMap.DirContId));
            google.maps.Event.addListener(_directions, "load", onDirectionsLoad);
            google.maps.Event.addListener(_directions, "error", onDirectionsErrors);

            setDefaultLocation();
        },

        getDirections: function(fromAddress, toAddress) {
            _directions.clear();
            _directions.load("from: " + fromAddress + " to: " + toAddress);
        },

        getStores: function(from) {
            _geocoder.getLocations(from, showAddress);
        },

        searchMap: function() {
            var to = _destInput.value;
            var from = _srcInput.value;
            _map.clearOverlays();
            _storeList.innerHTML = '';
            if (from && to) {
                LocationMap.getDirections(from + ', USA', to + ', USA');
            }
            else if (from) {
                LocationMap.getStores(from + ', USA', getRadius());
            }
        }
    };
})();

google.setOnLoadCallback(LocationMap.init);






