/**
 * Place Engine - a JQuery Plugin that allows you to quickly utilize the google places api via JS
 *
 * Paul Thompson
 * v 0.3 - 7/21/2011
 *
 * Changes from 0.3: made more info link have place search in gmaps
 *
 **/
(function ($) {

    var map = null;
    var markers_array = new Array();
    var directionsService = new google.maps.DirectionsService();

    var rendererOptions = {
        draggable: true,
        preserveViewport: true
    };

    var directionsDisplay = null;
    var centerMarker = null;
    var placesService = null;

    var methods = {

        init: function (options) {
            return this.each(function () {

                var valid = true;
                var $obj = this;
                var the_id = $obj.id;
                var request = null;

                //set user defined option, if they exist
                if (options) {
                    $.extend(settings, options);
                }

                //validate that the user provided the bare minimum:
                if (!settings.latitude || !settings.longitude) {
                    valid = false;
                    alert("Latitude and longitude are required");
                }

                if (valid) {
                    attrs.locale = new google.maps.LatLng(settings.latitude, settings.longitude);

                    map = new google.maps.Map(document.getElementById(the_id), {
                        mapTypeId: methods.get_map_type(),
                        center: attrs.locale,
                        zoom: settings.zoom
                    });

                    directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
                    placesService = new google.maps.places.PlacesService(map);

                    directionsDisplay.setMap(map);
                    directionsDisplay.setPanel(document.getElementById("directionsPanel"));

                    centerMarker = new google.maps.Marker({
                        position: attrs.locale,
                        map: map,
                        title: "Hello World!"
                    });

                    attrs.infowindow = new google.maps.InfoWindow();

                    google.maps.event.addListener(centerMarker, 'click', function () {
                        attrs.infowindow.setContent("<div>Keynote</div>");
                        attrs.infowindow.open(map, this);
                    });


                    if (settings.types || settings.name) {
                        request = methods.build_search();
                        methods.run_search(request);
                    }
                }

            });
        },
        route_directions: function (origin, destination, selectedMode) {
            var request = {
                origin: origin,
                destination: destination,
                travelMode: google.maps.TravelMode[selectedMode]
            };

            directionsService.route(request, function (response, status) {
                if (status == google.maps.DirectionsStatus.OK) {
                    directionsDisplay.setDirections(response);
                }
            });
        }
        ,
        output_results: function (results, status, $obj) {

            var html = "<table><tr><th>Place Name</th><th>Location</th><th>More Information?</th></tr>";
            var open_tags = "<tr><td>";
            var middle_tags = "</td><td>";
            var close_tags = "</tr></td>";
            var after = "</table>";
            var more_info_link = "";
            if (settings.html_container && settings.output_format != "table") {
                html = "<ul>";
                open_tags = "<li>";
                middle_tags = " - ";
                close_tags = "</li>";
                after = "</ul>";
            }

            var the_place = null;
            if (status == google.maps.places.PlacesServiceStatus.OK) {
                if (settings.debug) {
                    alert(status);
                }
                for (var i = 0; i < results.length; i++) {
                    the_place = results[i];
                    // <![cdata[ 
                    more_info_link = "<a href='http://maps.google.com/maps?ie=UTF-8&amp;fb=1&amp;q=" + the_place.name.replace(/'/g, "") + "&amp;hnear=" + the_place.vicinity.replace(/'/g, "") + "&amp;fb=1&amp;gl=us&amp;oi=local_result&amp;ct=image&amp;hq=" + the_place.name.replace(/'/g, "") + "' target='_blank'>Get More Information &raquo;</a>";
                    // ]]> 
                    methods.add_marker(the_place, more_info_link);

                    /*placesService.getDetails(place, function callback(place, status) {
                    if (status == google.maps.places.PlacesServiceStatus.OK) {
                    createMarker(place);
                    }
                    });*/


                    if (settings.html_container) {

                        html += open_tags + the_place.name + middle_tags + the_place.vicinity + middle_tags + more_info_link + close_tags;
                    }
                }
            }

            html += after;

            if (settings.html_container) {
                $(settings.html_container).html(html);
            }
        },
        add_marker: function (place, more_info_link) {
            var placeLoc = place.geometry.location;
            var image = new google.maps.MarkerImage(place.icon, new google.maps.Size(20, 20), new google.maps.Point(0, 0), // The origin
            new google.maps.Point(13, 18), new google.maps.Size(20, 20));

            var marker = new google.maps.Marker({
                map: map,
                position: place.geometry.location,
                icon: image
            });

            markers_array.push(marker);

            google.maps.event.addListener(marker, 'click', function () {
                attrs.infowindow.setContent("<div class='popup'>" + place.name + "<br />" + place.vicinity + "<br /><br />" + more_info_link);
                attrs.infowindow.open(map, this);
                methods.route_directions(centerMarker.position, place.geometry.location, "WALKING");
            });
        },
        clear_markers: function () {
            if (markers_array != null) {
                for (i in markers_array) {
                    markers_array[i].setMap(null);
                }
            }
        },
        build_search: function (types, name) {
            var r = { radius: settings.radius, location: attrs.locale };
            r.types = "";

            if (types != "NOTYPES") {
                if (types || settings.types) {
                    the_types = types ? types : settings.types;
                    r.types = the_types.split(",");
                }
            }


            if (name || settings.name) {
                settings.name = name != null ? name : settings.name;
                r.name = settings.name
            }

            return r
        },
        name_search: function (search_value) {
            var req = null;
            this.each(function () {
                req = methods.build_search("NOTYPES", search_value);
                methods.run_search(req);
            });
        },
        type_search: function (types) {
            var req = null;

            this.each(function () {
                var the_types = types != null ? types : this.rel;
                req = methods.build_search(the_types, "");
                methods.run_search(req);
            });
        },
        run_search: function (request) {
            if (settings.clear) {
                methods.clear_markers();
            }

            placesService.search(request, methods.output_results);
        },
        get_map_type: function () {
            var type = ""
            switch (settings.map_type) {
                case "terrain":
                    type = google.maps.MapTypeId.TERRAIN;
                    break;
                case "road":
                    type = google.maps.MapTypeId.ROADMAP;
                    break;
                case "hybrid":
                    type = google.maps.MapTypeId.HYBRID;
                    break;
            }

            return type;
        }


    }

    //attrs - need to be accessible only to the app, user can't override
    var attrs = {

        'results': "",
        'locale': null,
        'map': null,
        'infowindow': null,
        'public_methods': ["init", "clear_markers", "type_search", "name_search"]
    }

    var settings = {
        'longitude': false,
        'sensor': "false",
        'latitude': false,
        'zoom': 13,
        'radius': 5000,
        'types': false,
        'clear': true,
        'name': false,
        'map_type': "terrain",
        'language': 'en',
        'map_id': "map",
        "debug": false,
        'html_container': false,
        'output_format': "table"

    };



    $.fn.place_engine = function (method) {
        if (methods[method] && (attrs.public_methods.toString().indexOf(method) >= 0)) {
            return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
        }
        else if (typeof method === 'object' || !method) {
            return methods.init.apply(this, arguments);
        }
        else {
            $.error(' The method ' + method + ' is not a public place engine method');
        }
    };

})(jQuery);
