var map;
var mgr;
var markerData;
var markers = [];
var searchLatLng;
var searchBox;
var tickedCats;
var hasCategories;
var isDefault;

function GoogleMapsSearch(isDefaultSearch) {
    isDefault = isDefaultSearch;
    if (GBrowserIsCompatible()) {
        var mapContainer = document.getElementById(mapContainerID);
        map = new google.maps.Map2(document.getElementById(mapCanvasID));

        if (typeof (categoryMaximumResolution) != 'undefined') {
            GEvent.addListener(map, "zoomend", function(oldLevel, newLevel) {
                RestrictCategoryVisibilityByResolution(newLevel);
            });
        }

        // this will keep hidden markers hidden after a zoom
        GEvent.addListener(map, "addoverlay", function(marker) {
            if (marker.pleaseHideLater) {
                marker.hide()
            }
        });

        map.addControl(new google.maps.ScaleControl());
        map.addControl(new google.maps.SmallMapControl());

        searchBox = document.getElementById(searchBoxID);
        var localSch = new google.search.LocalSearch();
        localSch.setNoHtmlGeneration();
        localSch.setSearchCompleteCallback(this, function() {
            var resultOK = false;
            var resultLat = 0;
            var resultLng = 0;

            for (i = 0; i < localSch.results.length; i++) {
                resultLat = localSch.results[i].lat;
                resultLng = localSch.results[i].lng;

                // MAKE SURE RESULT IS WITHIN BOUNDS
                if (resultLat < minLat || resultLat > maxLat) continue;
                if (resultLng < minLng || resultLng > maxLng) continue;
                resultOK = true;

                mapContainer.className = 'gmMapContainerOuterVisible'

                searchLatLng = new google.maps.LatLng(resultLat, resultLng);
                map.setCenter(searchLatLng, maxZoom);

                mgr = new google.maps.MarkerManager(map);
                if (markers.length == 0 || alwaysRequestMarkers) {
                    var fullUrl = markerUrl;
                    fullUrl += markerUrl.indexOf('?') > -1 ? '&' : '?'
                    fullUrl += 'lat=' + resultLat + '&lng=' + resultLng

                    if (isDefaultSearch) {
                        fullUrl += '&isDefault=1';
                    }

                    GDownloadUrl(fullUrl, ProcessResults);
                }
                else {
                    UpdateMap(true);
                }
                break;
            }
            if (!resultOK) {
                searchBox.value = '';
                alert('Sorry, no results found, please enter a valid town or postcode.');
            }

        });
        localSch.execute(searchBox.value + ",UK");
    }
}

function ProcessResults(markerDataStr, statusCode) {
    if (statusCode != 200) return;
    markerData = eval('(' + markerDataStr + ')');

    var icon;
    if (markerData.icons) {
        icon = GetCustomIcon("your-location");
    }
    else {
        icon = new google.maps.Icon();
        icon.image = "http://maps.google.co.uk/mapfiles/arrow.png";
        icon.shadow = "http://maps.google.co.uk/mapfiles/arrowshadow.png";
        icon.iconSize = new google.maps.Size(39, 34);
        icon.shadowSize = new google.maps.Size(39, 34);
        icon.iconAnchor = new google.maps.Point(19, 34);
    }
    var yourLocMarker = new google.maps.Marker(searchLatLng, { clickable: false, icon: icon, title: 'Your location' });
    mgr.addMarker(yourLocMarker, 0);

    var bubbleUrl = markerData.bubble.url;
    bubbleUrl += bubbleUrl.indexOf('?') > -1 ? '&' : '?';
    bubbleUrl += 'slat=' + searchLatLng.lat() + '&slng=' + searchLatLng.lng();

    var resultsListContainer = $('.resultsListContainer')[0];
    var results = [];

    markers = [];
    for (var i = 0; i < markerData.markers.length; i++) {
        var markerSpec = markerData.markers[i];
        var latLng = new google.maps.LatLng(markerSpec.lat, markerSpec.lng)
        var marker;
        var title = (markerSpec.cat) ? markerSpec.catTitle + ': ' + markerSpec.title : markerSpec.title;
        if (markerData.icons) {
            var icon = (markerSpec.cat) ? GetCustomIcon(markerSpec.cat) : GetCustomIcon('marker');
            marker = new google.maps.Marker(latLng, { 'icon': icon, 'title': title });
        }
        else {
            marker = new google.maps.Marker(latLng, { 'title': title });
        }
        var thisBubbleUrl = bubbleUrl + '&mlat=' + latLng.lat() + '&mlng=' + latLng.lng() + '&id=' + markerSpec.id;
        marker.bindInfoWindowHtml('<iframe frameborder=\"0\" width=\"' + markerData.bubble.width + '\" height=\"' + markerData.bubble.height + '\" src=\"' + thisBubbleUrl + '\"></iframe>');
        markers.push(marker);

        if (resultsListContainer != null) {
            var distanceInMetres = latLng.distanceFrom(searchLatLng);
            var distanceInMiles = distanceInMetres * 0.000621371192;
            var distanceInKm = distanceInMetres * 0.001;
            var decimalPlaces = 1;
            var roundedDistanceMiles = Math.round(distanceInMiles * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
            var roundedDistanceKm = Math.round(distanceInKm * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
            results.push({ guid: markerSpec.id, distanceValue: distanceInMetres, distance: roundedDistanceMiles + " miles (" + roundedDistanceKm + " km)" });
        }
    }
    if (resultsListContainer != null) {

        results.sort(sortByDistance);

        var guids = [];
        var distances = [];

        var numToShow = results.length;
        if (numToShow > 20) {
            numToShow = 20;
        }

        for (i = 0; i < numToShow; i++) {
            guids.push(results[i].guid);
            distances.push(results[i].distance);
        }

        jQuery.post(linkPanelUrl, { guids: guids, Distance: distances }, function(linkPanelContent) {
            $(resultsListContainer).html(linkPanelContent);
        }, "html");
    }

    if (markers.length == 0) {
        searchBox.value = '';
        alert('Sorry, no results found for the town or postcode you entered.');
        mgr.refresh();
        return;
    }

    UpdateMap(true);
}

function sortByDistance(a, b) {
    return a.distanceValue - b.distanceValue;
}

function UpdateMap(fullUpdate) {
    // fullUpdate IS TRUE AFTER A SEARCH AND FALSE AFTER TICKING/UNTICKING A CATEGORY

    hasCategories = (catListID != '');
    if (hasCategories) {
        tickedCats = [];
        var catListDiv = document.getElementById(catListID);
        for (var i = 0; i < catListDiv.childNodes.length; i++) {
            var cb = catListDiv.childNodes[i].childNodes[0];
            if (cb.checked) tickedCats.push(cb.value + ': ');
        }
    }

    var lowestDist = 999999;
    var nearLatLng;
    for (var i = 0; i < markers.length; i++) {
        var markerVisible = !hasCategories;
        var marker = markers[i];
        if (hasCategories) {
            for (var j = 0; j < tickedCats.length; j++) {
                var title = marker.getTitle();
                var cat = tickedCats[j];
                if (title.indexOf(cat) == 0) {
                    if (!fullUpdate) {
                        marker.show();
                        marker.pleaseHideLater = false;
                    }
                    markerVisible = true;
                    break;
                }
            }
            if (!markerVisible && !fullUpdate) {
                marker.hide();
                marker.pleaseHideLater = true;
            }
        }

        if (markerVisible && fullUpdate) {
            var markerLatLng = marker.getLatLng();
            var dist = markerLatLng.distanceFrom(searchLatLng);
            if (dist < lowestDist) {
                lowestDist = dist;
                nearLatLng = markerLatLng;
            }
        }
    }

    if (fullUpdate) {
        if (nearLatLng) {
            var bounds = new google.maps.LatLngBounds();
            bounds.extend(searchLatLng);
            bounds.extend(nearLatLng);
            map.setCenter(bounds.getCenter());
            var zoomLevel = map.getBoundsZoomLevel(bounds);
            if (zoomLevel > maxZoom) zoomLevel = maxZoom;
            map.setZoom(zoomLevel);
        }

        mgr.addMarkers(markers, 0);
        mgr.refresh();
    }
    if (hasCategories && fullUpdate) {
        // REDO UpdateMap TO REMOVE UNWANTED MARKERS
        UpdateMap(false);
    }
}

function GoogleMapsReset(mapContainerID) {
    var mapContainer = document.getElementById(mapContainerID);
    mapContainer.className = 'gmMapContainerOuterHidden'
}

function GetCustomIcon(name) {
    var icon = new google.maps.Icon();
    icon.image = markerData.icons.src + name + '.png';
    icon.shadow = markerData.icons.src + 'shadow.png';
    icon.transparent = markerData.icons.src + 'transparent.png';
    icon.iconSize = markerData.icons.iconSize;
    icon.shadowSize = markerData.icons.shadowSize;
    icon.iconAnchor = markerData.icons.iconAnchor;
    icon.infoWindowAnchor = markerData.icons.infoWindowAnchor;
    return icon;
}

function RestrictCategoryVisibilityByResolution(level) {
    for (var i = 0; i < categoryMaximumResolution.length; i++) {
        var cb = document.getElementById(categoryMaximumResolution[i].categoryCheckboxID);
        if (level > eval(categoryMaximumResolution[i].maxResolution)) {
            cb.checked = false;
            cb.disabled = true;
        }
        else {
            cb.disabled = false;
        }
    }

    UpdateMap();
}

$(document).ready(function() {
    if (defaultSearchLocation) {
        var sb = $('#' + searchBoxID);
        sb.val(defaultSearchLocation);
        GoogleMapsSearch(true);
        sb.val('');
    }
});
