var googlemap;
var markerLoader;
var lockZoom = true;

var markers = new Array();
var homemarker;

var areas_cache = new Object();

function markersLoaded()
{
    // if xmlhttp shows "loaded"
    if (markerLoader.readyState==4)
    {
        // if "OK"
        if (markerLoader.status==200)
        {
            var markerdata = eval(markerLoader.responseText);
            buildMarkers(markerdata);
        } else
        {
            alert("Problem retrieving XML data");
        }
    }
}

function loadMarkers(event)
{
    var bounds = googlemap.getBounds();
    var sw = bounds.getSouthWest();
    var ne = bounds.getNorthEast();
    var url = "@@geo_getObjectsBoundedBy?lat_min=" + sw.lat() + "&lng_min=" + sw.lng() + "&lat_max=" + ne.lat() + "&lng_max="+ ne.lng();

    var filterby = $('#filterby').val()
    if (filterby != null) {
        var filterbyval = filterby + ':list';
        filtervals = getFilterByValues("input:checked[name='"+ filterbyval + "']");
        joined = filtervals.join('&' + filterbyval + '=')
        url = url + '&filterby=' + filterby + '&' + filterbyval + '=' + joined
    }

    lockZoom = (event != null) ? true : false;

    markerLoader = GXmlHttp.create();
    markerLoader.onreadystatechange=markersLoaded;

    markerLoader.open("GET",url,true);
    markerLoader.send(null);
}


function getFilterByValues(filter) {
    var filtervalues = []
    $(filter).each(function() {
        filtervalues.push($(this).val());
    });
    return filtervalues
}

function buildMarkers(markerdata)
{
    var bounds = googlemap.getBounds()
    var lat_min = bounds.getSouthWest().lat();
    var lat_max = bounds.getNorthEast().lat();
    var lng_min = bounds.getSouthWest().lng();
    var lng_max = bounds.getNorthEast().lng();
    var change = false;
    markerOptions = {};

    /// Because of grouping we have to delete all markers before adding new ones
    for (var j = 0; j < markers.length; j++)
    {
        var marker = markers[j];
        googlemap.removeOverlay(marker);

    }

    showSearchResults(markerdata)

    /// now create new markers
    for (var i = 0; i < markerdata.length; i++)
    {
        var m = markerdata[i];
        var markerIcon = new GIcon(G_DEFAULT_ICON);
        var imgurl = m.markericon ? m.markericon :"http://maps.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";
        markerIcon.image = imgurl;


        // Set up our GMarkerOptions object
        markerOptions = { icon:markerIcon };

        var marker = new GMarker(new GLatLng(m.lat, m.lng), markerOptions)

        marker.objectData = m;
        googlemap.addOverlay(marker);
        if (m.objects.length == 1) {
            GEvent.addListener(marker, "click", function(marker) {
                GDownloadUrl(this.objectData.objects[0].viewurl, function(data) {
                    googlemap.openInfoWindowHtml(new GLatLng(marker.y, marker.x), data, {});
                } )
            } )
        } else {
            GEvent.addListener(marker, "click", showLocationInfo);
        }
        markers.push(marker);

        // recalculate boundaries
        if (m.lat < lat_min) {
            lat_min = m.lat;
            change = true;
        } else if (m.lat > lat_max) {
            lat_max = m.lat;
            change = true;
        }
        if (m.lng < lng_min) {
            lng_min = m.lng;
            change = true;
        } else if (m.lng > lng_max) {
            lng_max = m.lng;
            change = true;
        }
    }

    if (change && !lockZoom)
        geo_zoomTo(lat_min, lng_min, lat_max, lng_max);
}


function showSearchResults(markerdata) {
    // remove former results
    $('#mapsearchresults > div').remove();
    var sum = 0;
    var maxItems = mapsConfig.google.maxSearchResultItems ? mapsConfig.google.maxSearchResultItems : 6;

    for (var i = 0; i < markerdata.length; i++)
    {
        var m = markerdata[i];
        sum += i + m.objects.length;

        if (sum >= maxItems)
          break;

        for (var j = 0; j < m.objects.length; j++) {
          $.get(m.objects[j].searchresulturl, {poslat:mapsConfig.google.initLat, poslng:mapsConfig.google.initLng},
          function(data) {
            $(data).hide().appendTo('#mapsearchresults').fadeIn('fast');
          })
        }
    }
}

function loadAreas()
{
    var url = portal_url+"/@@geo_getAllAreas";

    var areaLoader = GXmlHttp.create();
    areaLoader.onreadystatechange=function() {
    // if xmlhttp shows "loaded"
    if (areaLoader.readyState==4)
    {
        // if "OK"
        if (areaLoader.status==200)
        {
            var area_urls = eval(areaLoader.responseText);
            for(var i = 0; i < area_urls.length; i++)
            {
                loadAreaFromURL(area_urls[i]+"/get_json");
            }
        } else
        {
            alert("Problem retrieving a list of area URLS to load");
        }
    }
    };

    areaLoader.open("GET",url,true);
    areaLoader.send(null);

}

function loadAreaFromURL(url)
{
    var areaLoader = GXmlHttp.create();
    areaLoader.onreadystatechange=function() {
    // if xmlhttp shows "loaded"
    if (areaLoader.readyState==4)
    {
        // if "OK"
        if (areaLoader.status==200)
        {
            var area_data = eval(areaLoader.responseText);
            buildArea(area_data[0]);
        } else
        {
            alert("Problem retrieving data for area from "+ url);
        }
    }
    };

    areaLoader.open("GET",url,true);
    areaLoader.send(null);

}


function buildArea(area_data)
{
    var polyPoints = new Array();

    for (var i = 0; i < area_data.points.length; i++)
    {
        var p = area_data.points[i];
        polyPoints.push(new GLatLng(p[0],p[1]));
    }

    //var center = new GLatLng((lat_min+lat_max)/2, (lng_min+lng_max)/2);

    var lineColor = area_data.lineColor;
    var lineWeight= area_data.lineWidth;
    var opacity = area_data.opacity;
    var fillColor = area_data.fillColor;
    var polyShape = new GPolygon(polyPoints,lineColor,lineWeight,opacity,fillColor,opacity);

    googlemap.addOverlay(polyShape);

    var markerOptions = {};
    var markerIcon = new GIcon(G_DEFAULT_ICON);
    markerIcon.image = area_data.objects[0].icon;
    // Set up our GMarkerOptions object
    markerOptions = { icon:markerIcon };

    var marker = new GMarker(new GLatLng(area_data.centroid[0], area_data.centroid[1]), markerOptions)

    marker.objectData = area_data;
    googlemap.addOverlay(marker);
    GEvent.addListener( marker, "click", showAreaInfo );

}

function showAreaInfo()
{
    var maxContentDiv = document.createElement('div');
    maxContentDiv.innerHTML = 'Loading...';
    var opts = {};
    var html = "<p>No additional information</p>";

    if (this.objectData.objects.length == 1) // single object
    {
        var obj = this.objectData.objects[0];
        html='<h1><img src="'+obj.icon+'" /> '+obj.title+'</h1>';
        html += '<p>';
        if (obj.description) { html +=  "<p>"+obj.description+"</p>"; }
        if (obj.url) { html +=  '<a href="'+obj.url+'">more</a>'; }

        var bounds = ' ' + this.objectData.bounds.lat1 +', '+
                            this.objectData.bounds.lng1 +', '+
                            this.objectData.bounds.lat2 +', '+
                            this.objectData.bounds.lng2 ;

        html += ' <a href="javascript:geo_zoomTo('+ bounds + ')">zoom into view</a> ';
        html += '</p>';
        opts = { maxContent: maxContentDiv, maxTitle: "More Info" };

    }

    googlemap.openInfoWindowHtml(this.getLatLng(), html, opts);

    var iw = googlemap.getInfoWindow();

    iw.objectId = this.objectId;

    GEvent.addListener(iw, "maximizeclick", function() {
        GDownloadUrl(this.objectData.objects[0].url, function(data) {
            maxContentDiv.innerHTML = data;
        } )
    } )
}


function showLocationInfo()
{
    var maxContentDiv = document.createElement('div');
    maxContentDiv.innerHTML = 'Loading...';
    var opts = {};
    var html = "<p>No additional information</p>";

    if (this.objectData.objects.length > 1) // more than one object at the same location
    {
        var html="<h1>Multiple items</h1>";
        html+="<ul>";
        for (var i = 0; i<this.objectData.objects.length; i++)
        {
            var obj = this.objectData.objects[i];
            html+='<li style="list-style:none;"><a href="'+obj.url+'"><img src="'+obj.icon+'" /> '+obj.title+"</a></li>";
        }

        var bounds = ' ' + this.objectData.bounds.lat_min +', '+
                            this.objectData.bounds.lng_min +', '+
                            this.objectData.bounds.lat_max +', '+
                            this.objectData.bounds.lng_max ;

        if (this.objectData.count > this.objectData.objects.length)
        {
            html += '<p><a href="javascript:geo_zoomTo('+ bounds + ')">Zoom in</a> to see all <b>' + this.objectData.count + '</b> items in this area</p>';
        } else
        {
           // html += '<p><a href="javascript:geo_zoomTo('+ bounds + ')">Zoom in</a> to see these items</p>';
        }
    }

    googlemap.openInfoWindowHtml(this.getLatLng(), html, opts);

    var iw = googlemap.getInfoWindow();

    iw.objectId = this.objectId;

    GEvent.addListener(iw, "maximizeclick", function() {
        GDownloadUrl(this.objectData.objects[0].url, function(data) {
            maxContentDiv.innerHTML = data;
        } )
    } )
}

function geo_zoomTo(lat_min, lng_min, lat_max, lng_max)
{
    var zoom = googlemap.getBoundsZoomLevel(new GLatLngBounds(new GLatLng(lat_min, lng_min), new GLatLng(lat_max,lng_max)));
    var lat = (lat_min+lat_max)/2;
    var lng = (lng_min+lng_max)/2;
    googlemap.setCenter(new GLatLng(lat, lng), zoom);
}

function prepareLoadMarkers()
{
    // simply used to distinguish when the map was dragged and when it
    // was recalculated because the user searched for an address. If the
    // map was panned around, we would like to lock the zoom.
    loadMarkers('drag');
}


// used to determine the current position of the user.
function navigatorGeoSucess(position) {
  mapsConfig.google.initLat = position.coords.latitude;
  mapsConfig.google.initLng = position.coords.longitude;
  initSearchMap(position.coords.latitude, position.coords.longitude)
}

function navigatorGeoFailed(error) {
  initSearchMap(mapsConfig.google.initLat, mapsConfig.google.initLng);
}


/// ENTRY POINT
function initSearchMap(initLat, initLng) {
    if (GBrowserIsCompatible()) {

        mapdiv = document.getElementById("map");

        googlemap = new GMap2(mapdiv);
        googlemap.setCenter(new GLatLng(initLat,
            initLng), mapsConfig.google.initZoom);

        googlemap.addControl(new GLargeMapControl());
        googlemap.enableDoubleClickZoom();

        // load initial markers
        var handle = GEvent.addListener(googlemap, "dragend", prepareLoadMarkers);
        loadMarkers();

        var homeIcon = new GIcon(G_DEFAULT_ICON);
        homeIcon.image = "home_icon.png";

        // Set up our GMarkerOptions object
        markerOptions = { icon:homeIcon };

        homemarker = new GMarker(new GLatLng(initLat, initLng), markerOptions);
        googlemap.addOverlay(homemarker);

        homemarker.openInfoWindowHtml("<b>You are here</b><br/>Click on icons to see more info.");

    } else {
        var mapdiv = document.getElementById("map");
        mapdiv.style.display = "none";
    }
}

