/*
 * this is a simple search for via location based data.
 *
 * google maps is used for display of this data
 *
 * the implementation requires some markup
 *
 * <div class="haendlersuche">
 *
 * entry field for location
 * <form>
 * the em is a hint, which will be red on error
 * <label><em></em></label>
 * <input type="text"></input>
 * </form
 *
 * placeholder for the map
 * <div class="haendlersuche-map"></div>
 * </div>
 * <div class="haendlersuche haendlersuche-results">
 *
 * to display empty results
 * <span class="haendlersuche-noresults-hint"></span>
 *
 * to display results in a list form
 * <ul>
 *
 * </ul>
 * </div>
 *
 * it will call the options.queryurl url with parameters lat and lng
 * if options.queryurl is not set it will call cratoni-haendlersuche-query.php
 *
 * the call needs to return an xml with the following basic structure
 *
 * <result>
 * <marker name="" name="" strasse="" ort="" land="" bundesland="" webaddress="" telefon="" fax="" email="" lat="" lng="" distance=""/>
 * </result>
 *
 *
 */
// create namespace
var cratoni = {};
(function(){
    cratoni.i18n = {};
    cratoni.haendlersuche = function(options){
        var mapNode           = $('.haendlersuche .haendlersuche-map')[0];
        var DEFAULT_LOCATION = new google.maps.LatLng(48.85802, 9.55156);
        var DEFAULT_ZOOMLEVEL = 8;
        var queryurl = options.queryurl || "cratoni-haendlersuche-query.php";
        /*
         * proudly inspired by http://code.google.com/intl/de/apis/maps/articles/phpsqlsearch.html
         * das basiert hierauf: http://en.wikipedia.org/wiki/Haversine_formula
         */
        var map, geocoder;

        function createMarker(point, markerData) {
            var marker = new google.maps.Marker(point);
            var html = '<strong>' + markerData.name + '</strong><br/>' + markerData.strasse + "<br/>" + markerData.ort + "<br/>" + markerData.bundesland;
            html = html + "<br/>";
            if(markerData.telefon && markerData.telefon !== "0"){
                html = html + "<br/>" + cratoni.i18n.phone + ": " + markerData.telefon;
            }
            if(markerData.email && markerData.email !== "0"){
                html = html + "<br/>" + cratoni.i18n.email + ": " + markerData.email;
            }
            if(markerData.webaddress && markerData.webaddress !== "0"){
                html = html + "<br/><a href=\"http://" + markerData.webaddress + "\" title=\""+ markerData.name + "\">" + markerData.name + "</a>";
            }
            google.maps.Event.addListener(marker, 'click', function() {
                marker.openInfoWindowHtml(html);
            });
            return marker;
        }
        function createSidebarEntry(marker, markerData) {
            var div = document.createElement('li');
            div = $(div);
            if(markerData.isdistributor) {
                div.addClass('distributor');
            }
            var html = '<strong>' + markerData.name + '</strong><br/>' + (markerData.strasse === "0" ? "" : markerData.strasse) + "<br/>" + markerData.ort + "<br/>" + markerData.bundesland;
            div.html(html).css('cursor', 'pointer').click(function(event) {
                google.maps.Event.trigger(marker, 'click');
            }).mouseover(function(event) {
                div.addClass("hover");
            }).mouseout(function() {
                div.removeClass("hover");
            });
            return div[0];
        }
        var handleData = function(data, center) {
            var xml = google.maps.Xml.parse(data);
            var markers = xml.documentElement.getElementsByTagName('marker');
            map.clearOverlays();
            var sidebar = $('.haendlersuche .haendlersuche-results ul');
            sidebar.children().remove();
            if (markers.length === 0) {
                $(".haendlersuche .haendlersuche-noresults-hint").removeClass("haendlersuche-hidden");
                map.setCenter(DEFAULT_LOCATION, DEFAULT_ZOOMLEVEL);
                return;
            } else {
                $(".haendlersuche .haendlersuche-noresults-hint").addClass("haendlersuche-hidden");
            }

            var bounds = new google.maps.LatLngBounds();
            for (var i = 0; i < markers.length; i++) {
                var markerData = {
                    name            : markers[i].getAttribute('name'),
                    strasse         : markers[i].getAttribute('strasse'),
                    ort             : markers[i].getAttribute('ort'),
                    land            : markers[i].getAttribute('land'),
                    bundesland      : markers[i].getAttribute('bundesland'),
                    webaddress      : markers[i].getAttribute('webaddress'),
                    telefon         : markers[i].getAttribute('telefon'),
                    fax             : markers[i].getAttribute('fax'),
                    email           : markers[i].getAttribute('email'),
                    lat             : markers[i].getAttribute('lat'),
                    lng             : parseFloat(markers[i].getAttribute('lng')),
                    distance        : parseFloat(markers[i].getAttribute('distance')),
                    isdistributor   : markers[i].getAttribute('isdistributor') === "1",
                };

                var point = new google.maps.LatLng(markerData.lat, markerData.lng);

                var marker = createMarker(point, markerData);
                map.addOverlay(marker);
                var sidebarEntry = createSidebarEntry(marker, markerData);
                sidebar.append(sidebarEntry);
                bounds.extend(point);
            }
            //add own position
            bounds.extend(center);
            map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));
        };

        function searchLocationsNear(center) {
            var searchUrl = queryurl + '?lat=' + center.lat() + '&lng=' + center.lng();
            google.maps.DownloadUrl(searchUrl, function(data){
                handleData(data, center);
            });
       }

        function load() {
            if (google.maps.BrowserIsCompatible()) {
                geocoder = new google.maps.ClientGeocoder();
                map = new google.maps.Map2(mapNode);
                map.addControl(new google.maps.SmallMapControl());
                map.addControl(new google.maps.MapTypeControl());
                map.setCenter(DEFAULT_LOCATION, DEFAULT_ZOOMLEVEL);
                map.enableScrollWheelZoom();
                new google.maps.KeyboardHandler(map);
            }
            try {
                /*
                 * try to read geolocation via HTML 5 from Browser
                 * http://dev.w3.org/geo/api/spec-source.html
                 */
                if(options.doGeolocation){
                    if(navigator.geolocation) {
                        navigator.geolocation.getCurrentPosition(function(position){
                            var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                            searchLocationsNear(latLng);
                            geocoder.getLocations(latLng, function(response){
                                if (!response || response.Status.code !== 200) {
                                    return;
                                }else{
                                    if(response.Placemark[0]) {
                                        $(".haendlersuche form input").val(response.Placemark[0].address);
                                    }
                                }
                            });
                        });
                    }
                }
            } catch(error) {
                //fail silently if geolocation lookup fails
            }
        }
        load();

        function searchLocations() {
           var address = $(".haendlersuche form input")[0].value;
           geocoder.getLatLng(address, function(latlng) {
               if (!latlng) {
                   $(".haendlersuche form label em").css("color", "red");
               } else {
                   $(".haendlersuche form label em").css("color", null);
                   searchLocationsNear(latlng);
               }
           });
        }

        $(".haendlersuche form").submit(function(event){
            event.preventDefault();
             searchLocations();
        });
    };
}());
