(function ($) {

    var listjs = WPsettings.template+"/storelocations/final.js", // store list file location
        stores = []; // array to hold the returned json

    // google maps objects
    var geocoder, map;

    /*
     * Setup the google map and grab the store list json
     */
    var mapsInitialize = function () {
        geocoder = new GClientGeocoder();

        if (GBrowserIsCompatible()) {
            map = new GMap2(document.getElementById("mapContainer"));
            map.setCenter(new GLatLng(37.4419, -122.1419), 13);
            map.addControl(new GSmallMapControl());
        }

        $.get(listjs, function (data) {
            if (data) {
                stores = data;
            }
        }, 'json');
    }

    /*
     * Validate a zip code for US & Canada
     */
    var validateZip = function (code) {
        var regex = /(^\d{5}(-\d{4})?$)|(^[ABCEGHJKLMNPRSTVXY]{1}\d{1}[A-Z]{1} *\d{1}[A-Z]{1}\d{1}$)/;

        return regex.test(code);
    }

    /*
     * On form submit, use the zip code to get a list of stores
     */
    var showLocationSubmit = function () {
        var $list = $('#list'),
            $zipcode = $('#zipcode'),
            zip = $zipcode.val();

        map.clearOverlays();
        $list.html('');

        if (validateZip(zip)) {
            popuplateList(zip);
        } else {
            alert("Please enter a valid zip code for the US or Canada.");
        }

        return false;
    }

    /*
     * Pad zeros
     */
    $.strPad = function(i,l,s) {
        var o = i.toString();
        if (!s) { s = '0'; }
        while (o.length < l) {
            o = s + o;
        }
        return o;
    };

    /*
     * Populate the list with data using this zip code
     */
    var popuplateList = function (zip) {
        geocoder.getLocations(zip, function (response) {

            if (!response || response.Status.code != 200) {
                alert("Sorry, we were unable to find the location of your zipcode");
                return false;
            }

            if (response.Status.code == 602) {
                alert("2 or more locations was found for pick up or drop off locations, please try again with more accurate criteria.");
                return false;
            }

            var homeLat = response.Placemark[0].Point.coordinates[1],
                homeLon = response.Placemark[0].Point.coordinates[0],
                zipCodeLocation = new GLatLng(homeLat, homeLon, true),
                htmltable = "<div id=\"tableContainer\">",
                items_per_page = 5,
                cnt = 0,
                i = 0;

            // loop through stores, if within distance add to locals
            $.each(stores, function () {
                var distance = getDistance(homeLat, homeLon, this.bg_lat, this.bg_long);
                if ((distance * 0.6214) < 50) {
                    i++;

                    if (cnt == 0) {
                        htmltable += "<ul id=\"results\">";
                    }
                    cnt++;

                    // set the address
                    this.Zip = $.strPad(this.Zip, 5, '0');
                    var address = this.Address1 + "<br/>";
                    if (this.Address2) address += this.Address2 + "<br/>";
                    address += this.City + ", " + this.State + " " + this.Zip;
                    if (this.Phone) address += "<br />Phone: " + this.Phone;
                    if (this.Website) address += "<br /><a target='_blank' href='http://" + this.Website + "'>" + this.Website + "</a>";

                    // add the marker to the map
                    var point = new GLatLng(this.bg_lat, this.bg_long);
                    map.addOverlay(createMarker(point, this.Store + "<br/>" + address));

                    // add a new entry to the results table
                    htmltable += "<li class=\"result\"><div class=\"store\">" + this.Store + "</div><div class=\"address\">" + address + "</div></li>";

                    if (cnt == items_per_page || i == stores.length) {
                        cnt = 0;
                        htmltable += "</ul>";
                    }

                }
            });
            htmltable += "</div>";

            if (htmltable != "<div id=\"tableContainer\"></div>") {
                $('#list').html(htmltable);

                jQuery('#tableContainer').before('<div id="pagernav" class="nav">').cycle({
                    fx:     'fade',
                    speed:  'fast',
                    timeout: 0,
                    pager:  '#pagernav'
                });

                map.setCenter(new GLatLng(homeLat, homeLon), 10);

            } else {
                $('#list').html("<p>Sorry, no stores found within 50 miles from your location.</p>");
            }

        });
    }

    /*
     * Add a marker to the map
     */
    function createMarker(point, name) {
        var marker = new GMarker(point);

        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(name);
        });

        return marker;
    }

    /*
     * Convert numbers to radians
     */
    Math.toRad = function (num) {
        return (num * Math.PI/180);
    }

    /*
     * Get the distance between two points
     *
     * http://www.movable-type.co.uk/scripts/latlong.html
     */

    var getDistance = function (lat1, lon1, lat2, lon2){
        var R = 6371; // Radius

        var dLat = Math.toRad(lat2-lat1);
        var dLon = Math.toRad(lon2-lon1);

        var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
            Math.cos(Math.toRad(lat1)) * Math.cos(Math.toRad(lat2)) *
            Math.sin(dLon/2) * Math.sin(dLon/2);

        var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        var d = R * c;

        return d;
    }

    /*
     * Get everything started
     */
    $(document).ready(function () {
        if ($('body').hasClass('page-template-page-stores-php')) {
            mapsInitialize();

            // set a submit handler for our form
            $('form#showLocation').submit(showLocationSubmit);
        }
    });

}(jQuery));