var MapConfig = {
    testPricingUrl: '/std-test-pricing/'
};

function ieArrayFix() {
  Array.prototype.ieIndexOf = function(k){
    var len = this.length;
    for(i=0;i<len;i++){
      if(this[i] == k){
        return i;
      }
    }
    return -1;
  };
}

function getLocationsByCoords(northeast, southwest, center) {
        // Lookup locations by latitude and longitude
        var max_lat = northeast.lat().toFixed(4);
        var min_lat = southwest.lat().toFixed(4);
        var max_lng = northeast.lng().toFixed(4);
        var min_lng = southwest.lng().toFixed(4);
        var ctr_lat = center.lat().toFixed(4);
        var ctr_lng = center.lng().toFixed(4);
        
        $.getJSON('/locations/', {'max_lat': max_lat, 'min_lat': min_lat, 'max_lng': max_lng, 'min_lng': min_lng, 'ctr_lat': ctr_lat, 'ctr_lng': ctr_lng},
                function (all_locations) {
                    min_distance = 50;
                        addLocationsToMap(all_locations, false);
                        $("#events").trigger("getLocationsByCoordsComplete");
                }
        );
}


function getLocationsByAddress(location, address, max_distance, max_results) {
        // Lookup locations by address (python handles geocode)
        $.getJSON('/locaddress/',
                  {'location': location, 'address': address,
                   'max_distance': max_distance, 'max_results': max_results,
                   'user_set': true},
                function (response) {
                        $("#locations").html('');
                        map.clearOverlays();
                    var all_locations = response.locations;
                    min_distance = response.min_distance;
                        addLocationsToMap(all_locations, true);
                        $("#events").trigger("getLocationsByAddressComplete");
                }
        );
}


function addLocationsToMap(location_data,is_first_load) {
        // Take location data for points and put them on the map
        
        var locations = new Array();
        location_list_html = '';
        if (existing_locations.length < 1) {
            $("#locations").html('');
        }
        locations_bounds = new GLatLngBounds();
        unBindEventListeners();
        ieArrayFix();
    if (typeof(min_distance) == 'undefined') {
        min_distance = 50;
    }
        
        if ((location_data.length < 1) && (existing_locations.length < 1)) {
                $("#locations").prepend('<li id="noresults"><div class="info">No results available</div></li>');
                bindEventListeners();
        } else if ((location_data.length > 0) && (location_data[0].error == 'bad_address')) {
            $("#locations").prepend('<li id="noresults"><div class="info" style="color: #d63333;">Could not find the address you entered. Please re-enter as Address, City, State Zip.</div></li>');
        } else if ((location_data.length > 0) && (location_data[0].error == 'none')) {
            // This happens when no locations are returned on a map pan/zoom
            // Just reenable bindings and move on
            $("#events").trigger("addLocationsToMapComplete");
        } else {
                if ((location_data.length > 99) && (existing_locations.length < 1)) {
                        $("#locations").prepend('<li id="100results"><div class="info"><b>More than 100 results returned. Only showing the first 100. Please refine your search or zoom in.</b></div></li>');
                }
                
                for (var i=0; ((i <= location_data.length) && (existing_locations.length < 100)); i++) {
                        if (i != location_data.length) {
                            if (existing_locations.ieIndexOf(location_data[i].pk) == '-1') {
                                    // Add the point
                                    pk = location_data[i].pk
                                    var point = convertLatLngToPoint(location_data[i].latitude, location_data[i].longitude);
                                locations[pk] = new createMarker(point, is_marker_clickable=true);
                                map.addOverlay(locations[pk]);
                                locations_bounds.extend(point);
                                marker_html = generateMarkerBubbleHTML(pk, location_data[i]);
                                locations[pk].bindInfoWindowHtml(marker_html);
                                GEvent.bind(locations[pk], 'click', {'pk': pk}, markerClickHandler);
                        
                                location_list_html = generateLocationListHTML(pk, location_data[i]);
                                $("#locations").append(location_list_html);
                                $("#location" + pk).bind("mousedown", {'marker': locations[pk]}, locationListClickHandler);
                                if (typeof(instant_pop_location) != 'undefined') {
                                        if (instant_pop_location == true) {
                                            GEvent.trigger(locations[pk], 'click');
                                            instant_pop_location = false;
                                        }
                                }
                                $("#location" + pk).addClass("clickable");
                                existing_locations.push(pk);
                        } else {
                            var point = convertLatLngToPoint(location_data[i].latitude, location_data[i].longitude);
                            locations_bounds.extend(point);
                        }
                        } else {
                                if (is_first_load == true) { 
                                        showInitialMarkers(); 
                                } else {
                                        showAllMarkers();       
                                }
                                
                                $("#events").trigger("addLocationsToMapComplete");
                                
                        }
                }
                
                if ((existing_locations.length > 99) && (typeof(are_too_many_locations_displayed) == 'undefined')) {
                are_too_many_locations_displayed = true
                $("#locations").prepend('<li id="100results"><div class="info"><b>More than 100 results returned. Only showing the first 100. Please try a new search.</b></div></li>');
            }
            
                if (min_distance > 50) {
                    if (min_already_visible == false) {
                        min_already_visible = true;
                        $("#locations").prepend('<li id="overmaxdistance"><div class="info"><b>No locations found within 50mi. Showing the closest locations.</b></div></li>');
                    } else {
                        $("#overmaxdistance").remove();
                        $("#locations").prepend('<li id="overmaxdistance"><div class="info"><b>No locations found within 50mi. Showing the closest locations.</b></div></li>');
                    }
                }
        }
}


function showInfoWindow(marker, marker_html) {
        marker.openInfoWindowHtml(marker_html);
}


function markerClickHandler() {
        // Handle a click on a map marker
        unHighlightLocation($(".selected").attr('id'));
        highlightLocation(this.pk);

        if ($('#locations').length > 0) {
            $("#locations").scrollTo($("#location" + this.pk), 1000);
    }
        
        $("#events").trigger("markerClickHandlerComplete");
}


function locationListClickHandler(event) {
        // Trigger a click event on a marker
        GEvent.trigger(event.data.marker, 'click');
        
        $("#events").trigger("locationListClickHandlerComplete");
}


function highlightLocation(element_id) {
    unHighlightLocation($(".selected").attr('id'));
    selectLocation(element_id);
    
        $("#location" + element_id).addClass("selected");
}


function unHighlightLocation(element_id) {
        $('#' + element_id).removeClass("selected");
}


function showAllMarkers() {
        // Resets the map zoom and center to include all bounds
        unBindEventListeners();
        //map.setZoom(map.getBoundsZoomLevel(locations_bounds));
        //map.setCenter(locations_bounds.getCenter());
        bindEventListeners();
        
        $("#events").trigger("showAllMarkersComplete");
}

function showInitialMarkers() {
        // Resets the map zoom and center to include all bounds
        unBindEventListeners();
        map.setZoom(map.getBoundsZoomLevel(locations_bounds));
        map.setCenter(locations_bounds.getCenter());
        bindEventListeners();
        
        $("#events").trigger("showAllMarkersComplete");
}

function bindEventListeners() {
        GEvent.addListener(map, 'zoomend', updateMapOnZoom);
        GEvent.addListener(map, 'dragend', updateMapOnDrag);
}


function unBindEventListeners() {
        GEvent.clearListeners(map, 'zoomend');
        GEvent.clearListeners(map, 'dragend');
}


function updateMapOnDrag() {
        // When the map is dragged look for all locations within the map bounds
        // Only updates if the map was moved more than ~20%
        unBindEventListeners();
        var map_bounds = map.getBounds();
        var map_ctr = map.getCenter();
        var map_ne = map_bounds.getNorthEast();
        var map_sw = map_bounds.getSouthWest();
        var bounds_ne = locations_bounds.getNorthEast();
                                
        var move_distance = distance_between_points(map_ne, bounds_ne);
        var map_size = distance_between_points(map_ne, map_sw);
        var percent_change = move_distance / map_size;
        
        if (percent_change > 0.2) {     
                var new_center = map.getCenter();
                var latitude = new_center.lat();
                var longitude = new_center.lng();
                
                getLocationsByCoords(map_ne, map_sw, map_ctr);
        }
        $("#events").trigger("updateMapOnDragComplete");
}


function updateMapOnZoom() {
        // When the zoom level changes look for all locations within map bounds
        unBindEventListeners();
        var map_bounds = map.getBounds();
        var map_ctr = map.getCenter();
        var map_ne = map_bounds.getNorthEast();
        var map_sw = map_bounds.getSouthWest();
        
        getLocationsByCoords(map_ne, map_sw, map_ctr);
}


function distance_between_points(point1, point2) {
        // Calculate the distance in km between two points
        var lat1 = point1.lat();
        var lon1 = point1.lng();
        var lat2 = point2.lat();
        var lon2 = point2.lng();
        
        var radius = 6371;
        var distance = Math.acos(
                                        Math.sin(lat1)
                                        * Math.sin(lat2)
                                        + Math.cos(lat1)
                                        * Math.cos(lat2)
                                        * Math.cos(lon2-lon1))
                                        * radius;
              
    return distance;
}


function processNewSearch() {
        // Look for values on page and handle the search
        location_search = $("#location_id").val();
        address_search = $("#address").val();
        max_distance = $("#max_distance").val();
        max_results = $("#max_results").val();
        locations_bounds = new GLatLngBounds();
        existing_locations = new Array();
        min_already_visible = false;
        
        if (max_distance == null) {
                max_distance = 25;
        }
        
        if (max_results == null) {
                max_results = 5;
        }
        
        getLocationsByAddress(location_search, address_search, max_distance, max_results);
        //$("#locationsdiv").html('');
        
        $("#events").trigger("processNewSearchComplete");
}


function geoCodeLocation(address) {
        // Geocode the address using Maps API
        geocoder.getLatLng(
                address,
                function(point) {
                        latlng = {'lat': point.lat(), 'lng': point.lng()};
                        $("#messages").append("geoCodeComplete<br>");
                }
        );
        
        $("#events").trigger("geoCodeLocationComplete");
}


function addMapToPage(map_id) {
        // Initialize the map
        map = new GMap2(document.getElementById(map_id));
        map.setCenter(new GLatLng(39.238128, -96.183553), 4);
        map.addControl(new GSmallZoomControl3D());
        map.addControl(new GScaleControl());
        map.setMapType(G_NORMAL_MAP);
        buttons = new Array();
        button_listeners = false;
        existing_locations = new Array();
        min_already_visible = false;
        onFullyLoaded();
        
        $("#events").trigger("addMapToPageComplete");
}


function createMarker(point, is_marker_clickable) {
        // Create marker objects
        if ((is_marker_clickable == null) || (is_marker_clickable == '')) {
                is_marker_clickable = true;
        }
        
        this.marker = new GMarker(point, {clickable: is_marker_clickable});
        
        return this.marker;
}


function convertLatLngToPoint(lat, lng) {
        // Create a GLatLng object from coordinates
        point = new GLatLng(lat, lng);
        
        return point;
}


function selectLocation(location_id) {
    // Set location in session
    location_selected = false;
    if (map_page == 'checkout') {
        $("#spinnerdiv").show();
        $(".order_details_text").hide();
    }
    $.getJSON('/set-location/', {'location_id': location_id},
        function(response) {
            if (response.pk == location_id) {
                if (map_page == 'checkout') {
                    // Update location in sidebar
                    location_selected = true;
                    locsummary = generateSummaryLocationHTML(response);                
                    $("#summarylocation").html(locsummary);
                    // if test location is direct bill, don't show the fees
                    // breakdown.
                    if (response.is_direct_bill == true) {
                      $('#fees_breakdown').show();
                    } else {
                      $('#fees_breakdown').hide();
                    }
                }
            } else {
                if (map_page == 'checkout') {
                    // Indicate that location didn't update
                    $("#summarylocation").html('<span class="orderlabel"><strong>Could not set your location at this time.</strong></span>');
                }
            }
            if (map_page == 'checkout') {
                $("#spinnerdiv").hide();
                $(".order_details_text").show();
            }
        }
    );
}


function generateSummaryLocationHTML(location) {
    // Generate HTML for the location in checkout summary
    if ((location.address2 != null) && (location.address2 != '')) {
                st_address = location.address1 + '<br>' + location.address2;
        } else {
                st_address = location.address1;
        }
    this.html = '<span class="orderlabel">Location:</span><span class="item">';
    this.html += st_address;
    this.html += '<br>' + location.city + ', ' + location.state + ' ' + location.zip;
    this.html += '<br></span><hr class="space" />';
    
    return this.html;
}


function generateLocationListHTML(index, data) {
        // HTML for location list bar
        this.index = index;
        this.data = data;
        
        if (this.data.address2 != null) {
                this.st_address = this.data.address1 + '<br>' + this.data.address2;
        } else {
                this.st_address = this.data.address1;
        }
        
        this.content = '';
        this.content += '<li id="location' + this.data.pk + '">';
        this.content += '<div class="info">';
        this.content += '<a href="#" onHover="highlightLocation(' + this.index + ');return false;">';
        this.content += '<div class="address" style="color:#222;font-weight:bold;">';
        this.content += '<div>' + this.st_address + '</div>';
        this.content += '<div>' + this.data.city + ', ' + this.data.state + ' ' + this.data.zip + '</div>';
        this.content += '</div></a>';
        if (this.data.distance) {
        this.content += '<div>Distance: ' + Math.round(this.data.distance) + ' mi.</div>';
        }
        this.content += '<div>Hours: ' + this.data.hours + '</div>';
    this.content += '<div><a href="' + MapConfig.testPricingUrl + '?address=' + escape(this.data.address1+' '+this.data.city + ', ' + this.data.state + ' ' + this.data.zip) + '" ';
    this.content += 'class="location_button" style="text-decoration:;font-size:125%; font-weight:bold;color:#2b7ebf;">Order &amp; Test Here</a></div>';
        this.content += '<a class="directions" style="color:#2b7ebf;" href="http://maps.google.com/maps?daddr=' + this.data.address1 + ' ' + this.data.city + ', ' + this.data.state + ' ' + this.data.zip + '" target="_blank">Get Driving Directions</a>';
        this.content += '<button class="select_location_button" style="margin:3px 0 0 0;">Select Location</button>';
        this.content += '</div>';
        this.content += '</li>';
        
        return this.content;
}


function generateMarkerBubbleHTML(index, data) {
        // HTML for marker bubble
        this.index = index;
        this.data = data;
        
        if (this.data.address2 != null) {
                this.st_address = this.data.address1 + '<br>' + this.data.address2;
        } else {
                this.st_address = this.data.address1;
        }
        
        this.content = '<div class="map-caption"">';
        this.content += '<div class="mapbubble">';
        this.content += '<div class="address">';
        this.content += '<div>' + this.st_address + '</div>';
        this.content += '<div>' + this.data.city + ', ' + this.data.state + ' ' + this.data.zip + '</div>';
        this.content += '</div>';
    this.content += '<div><a href="' + MapConfig.testPricingUrl + '?address=' + escape(this.data.address1+' '+this.data.city + ', ' + this.data.state + ' ' + this.data.zip) + '" ';
        this.content += 'style="text-decoration:none;font-size:125%; font-weight:bold;" class="location_button">Order &amp; Test Here</a></div>';
        this.content += '<a class="directions" href="http://maps.google.com/maps?daddr=' + this.data.address1 + ' ' + this.data.city + ', ' + this.data.state + ' ' + this.data.zip + '" target="_blank">Get Driving Directions</a>';
        this.content += '<div id="selected-indicator" class="green" style="margin-top:5px;font-weight:bold;"><img src="/static/i/green_check.gif"> Location Selected.</div>';
        
        return this.content;
}

function changeZoom(zoom_delta) {
    // Easily increase or decrease zoom level of map
    current_zoom = map.getZoom();
    new_zoom = current_zoom + zoom_delta;
    map.setZoom(new_zoom);
}

