(function (a) {
    window._googleMapsLoading = false;
    var j = {
        init: function (e) {
            function f(d) {
                a("body").append(a("<script />").attr("src", b.apiUrl + "?sensor=" + d + "&callback=googleMapsApiLoaded"))
            }
            function g() {
                if (b.homeLocation.lat && b.homeLocation.lng) {
                    latLng = new google.maps.LatLng(b.homeLocation.lat, b.homeLocation.lng);
                    a(c).trigger("locationFound.routePlanner", [latLng])
                } else j.geocode(b.homeLocation.address, function (d) {
                    a(c).trigger("locationFound.routePlanner", [d])
                }, b)
            }
            var c = this,
                i = false,
                b = {
                    loadApi: true,
                    apiUrl: "http://maps.google.com/maps/api/js",
                    region: "usa",
                    mapType: "roadmap",
                    zoom: 13,
                    units: "metric",
                    geolocation: {
                        enabled: true,
                        minAccuracy: 166E3,
                        timeout: 10
                    },
                    homeLocation: {
                        address: "1600 Pennsylvania Avenue NW, Washington, DC 20500"
                    },
                    cacheResults: true,
                    showInputFields: true,
                    labels: {
                        inputLabel: "Please enter your address to calculate the route to us:",
                        submitLabel: "Get directions",
                        placeholderLabel: "Enter your address here",
                        customMarker: false,
                        geolocationSearching: "Trying to determine your current location",
                        geolocationNotFound: "Unable to determine your current location. Please enter an address.",
                        geolocationFound: "The route shown is based on a guess of your current position. You can enter another address if our guess was wrong.",
                        printLabel: "Print directions"
                    },
                    printButton: true,
                    directions: {
                        draggable: true,
                        travelMode: "driving"
                    }
                };
            e && a.extend(true, b, e);
            if (b.loadApi) {
                if (!window._googleMapsLoading) {
                    window._googleMapsLoading = true;
                    f(b.geolocation.enabled ? "true" : "false")
                }
            } else a(window).trigger("mapsApiLoaded.routeplanner");
            a(window).bind("mapsApiLoaded.routePlanner", function () {
                jctx = a(c);
                jctx.data("settings", b);
                if (b.showInputFields) {
                    jctx.append(a('<div class="routeplanner-wrapper" />').append(a('<div class="routeplanner-direction-form" />').append(a("<p>").html(b.labels.inputLabel).append('<br /><input type="text" class="routeplanner-to" data-placeholder="' + b.labels.placeholderLabel + '" value="' + b.labels.placeholderLabel + '" />').append('<p class="routeplanner-geolocation">&nbsp;</p>').append('<input class="routeplanner-button" type="button" value="' + b.labels.submitLabel + '" />')))).append(a('<div class="routeplanner-directions" />'));
                    b.printButton && a(".routeplanner-direction-form > p", jctx).append('<input class="routeplanner-print" type="button" value="' + b.labels.printLabel + '" />');
                    width = a(".routeplanner-wrapper", jctx).width();
                    height = a(jctx).height() - a(".routeplanner-direction-form").height()
                } else {
                    jctx.append(a('<div class="routeplanner-wrapper" />')).append(a('<div class="routeplanner-directions" />'));
                    width = jctx.width();
                    height = jctx.height()
                }
                a(".routeplanner-wrapper", jctx).prepend(a('<div class="routeplanner-map" />').css({
                    width: width,
                    height: height
                }));
                a(".routeplanner-geolocation", c).hide();
                jctx.css("height", "auto");
                b.homeLocation ? g() : alert("You must at least set a home location")
            });
            a(".routeplanner-to", c).live("click", function () {
                a(this).val() == a(this).attr("data-placeholder") && a(this).val("")
            });
            a(".routeplanner-to", c).live("keyup", function (d) {
                d.keyCode == "13" && a(".routeplanner-direction-form input[type=button]", c).trigger("click")
            });
            a(".routeplanner-print", c).live("click", function () {
                a(c).trigger("print.routePlanner")
            });
            a(".routeplanner-button", c).live("click", function () {
                j.geocode(a(".routeplanner-to", c).val(), function (d) {
                    a(c).trigger("targetFound.routePlanner", [d])
                }, b)
            });
            a(c).bind("targetFound.routePlanner", function (d, h) {
                j.loadDirection(h, c, b)
            });
            a(c).bind("locationFound.routePlanner", function (d, h) {
                var l = {
                    zoom: b.zoom,
                    mapTypeId: google.maps.MapTypeId[b.mapType.toUpperCase()],
                    center: h
                };
                i = new google.maps.Map(a(".routeplanner-map", c)[0], l);
                a(c).data("map", i);
                if (b.homeLocation.address) new google.maps.Marker({
                    position: h,
                    map: i,
                    title: b.labels.customMarker.length ? b.labels.customMarker : b.homeLocation.address
                });
                b.homeLocation.latLng = h;
                if (b.geolocation.enabled && navigator.geolocation) {
                    a(".routeplanner-geolocation").show().html(b.labels.geolocationSearching);
                    navigator.geolocation.getCurrentPosition(function (k) {
                        if (k.coords && k.coords.accuracy <= b.geolocation.minAccuracy) {
                            a(".routeplanner-geolocation").html(b.labels.geolocationFound);
                            j.reverseGeocode(k.coords.latitude, k.coords.longitude, function (m) {
                                a(".routeplanner-to", c).val(m).attr("data-placeholder", m);
                                h = new google.maps.LatLng(k.coords.latitude, k.coords.longitude);
                                a(c).trigger("targetFound.routePlanner", [h])
                            }, b)
                        } else a(".routeplanner-geolocation").html(b.labels.geolocationNotFound);
                        a(c).trigger("ready.routePlanner")
                    }, function () {
                        a(".routeplanner-geolocation").html(b.labels.geolocationNotFound);
                        a(c).trigger("ready.routePlanner")
                    }, {
                        timeout: b.geolocation.timeout * 1E3
                    })
                } else a(c).trigger("ready.routePlanner")
            });
            a(c).bind("print.routePlanner", function () {
                a("iframe", c).remove();
                a(this).append('<iframe width="1" height="1"></iframe>');
                var d = a("iframe", c).hide();
                d = d[0].contentWindow || d[0].contentDocument;
                if (d.document) d = d.document;
                d.write('<html><head><title>Directions</title></head><body onload="this.print()">' + a(".routeplanner-directions").html() + "</body></html>");
                d.close()
            })
        },
        loadDirection: function (e, f, g) {
            a(f).trigger("directionsLoading.routeplanner", [e]);
            a(".routeplanner-directions", f).html("");
            var c = new google.maps.DirectionsService;
            directionsDisplay = new google.maps.DirectionsRenderer({
                draggable: g.directions.draggable
            });
            directionsDisplay.setMap(a(f).data("map"));
            directionsDisplay.setPanel(a(".routeplanner-directions", f)[0]);
            a(".routeplanner-print", f).hide();
            g = {
                destination: g.homeLocation.latLng,
                origin: e,
                unitSystem: google.maps.DirectionsUnitSystem[g.units.toUpperCase()],
                travelMode: google.maps.DirectionsTravelMode[g.directions.travelMode.toUpperCase()]
            };
            c.route(g, function (i, b) {
                if (b == google.maps.DirectionsStatus.OK) {
                    directionsDisplay.setDirections(i);
                    a(".routeplanner-print", f).show();
                    a(f).trigger("directionsLoaded.routePlanner")
                } else alert("Sorry. No results. Please check your address. " + e)
            })
        },
        geocode: function (e, f, g) {
            geocoder = new google.maps.Geocoder;
            if (typeof JSON !== "undefined" && g.cacheResults) try {
                cache = typeof window.localStorage !== "undefined" ? JSON.parse(localStorage.getItem(e)) : false
            } catch (c) {
                cache = false
            } else cache = false;
            if (cache) {
                latLng = new google.maps.LatLng(cache.lat, cache.lng);
                f(latLng)
            } else geocoder.geocode({
                address: e
            }, function (i, b) {
                if (b == google.maps.GeocoderStatus.OK) {
                    var d = {
                        lat: i[0].geometry.location.b,
                        lng: i[0].geometry.location.c
                    };
                    if (typeof JSON !== "undefined" && g.cacheResults) try {
                        typeof window.localStorage !== "undefined" && localStorage.setItem(e, JSON.stringify(d))
                    } catch (h) {}
                    f(i[0].geometry.location)
                } else alert("Geocode was not successful for the following reason: " + b)
            })
        },
        reverseGeocode: function (e, f, g, c) {
            geocoder = new google.maps.Geocoder;
            if (typeof JSON !== "undefined" && c.cacheResults) try {
                cache = typeof window.localStorage !== "undefined" ? JSON.parse(localStorage.getItem(JSON.stringify([e, f]))) : false
            } catch (i) {
                cache = false
            } else cache = false;
            if (cache) g(cache);
            else {
                var b = new google.maps.LatLng(e, f);
                geocoder.geocode({
                    latLng: b
                }, function (d, h) {
                    if (h == google.maps.GeocoderStatus.OK) {
                        var l = d[1].formatted_address;
                        if (typeof JSON !== "undefined" && c.cacheResults) try {
                            typeof window.localStorage !== "undefined" && localStorage.setItem(JSON.stringify([e, f]), JSON.stringify(l))
                        } catch (k) {}
                        g(d[1].formatted_address)
                    } else alert("Geocode was not successful for the following reason: " + h)
                })
            }
        },
        navigateTo: function (e) {
            var f = this;
            j.geocode(e, function (g) {
                j.loadDirection(g, f, a(f).data("settings"))
            }, a(f).data("settings"))
        },
        print: function () {
            a(this).trigger("print.routePlanner")
        }
    };
    a.fn.routePlanner = function (e) {
        argv = arguments;
        return this.each(function () {
            if (j[e]) return j[e].apply(this, Array.prototype.slice.call(argv, 1));
            else if (typeof e === "object" || !e) {
                options = [e];
                return j.init.apply(this, options)
            }
        })
    }
})(jQuery);

function googleMapsApiLoaded() {
    $(window).trigger("mapsApiLoaded.routePlanner")
};
