var displayedMarkers = {};
var latestBatch = {};
var startSelected = true;
var dupePoints = {};
var clusterTitleMax = 6;
var map;
var clusterCounts = [];
var dupes = {};

function createMap(setbounds) {
  map = new GMap2($('map'), {logoPassive:true});
      
  clusterer = new Clusterer(map);
  clusterer.SetMaxVisibleMarkers(200);
  clusterer.SetMinMarkersPerCluster(5);
  clusterer.SetMaxLinesPerInfoBox(clusterTitleMax);
  clusterer.SetIcon(fixedSizeClusterIcon());
  
  map.addControl(new GLargeMapControl());
  map.setCenter(new GLatLng(43.068887774169625, 3.515625), 1);
  map.enableScrollWheelZoom();
  setMapBounds();
  GEvent.addListener(map, "click", function(marker, point) {
    if (!startSelected){
      map.setCenter(point, 5);
      setZoomLimits();
    }		
	});
	GEvent.addListener(map, "moveend", function(marker, point) {
	  if (!startSelected) { setZoomLimits(); }
    setMapBounds();
		refreshPoints(false);	
		if ( listContents ) {
          submitListForm();
		}
	});
	refreshPoints(setbounds);
} //function createMap

function setZoomLimits() {
  startSelected = true;
  // Get the list of map types      
  mt = map.getMapTypes();
  // Overwrite the getMinimumResolution() and getMaximumResolution() methods
  for (var i=0; i<mt.length; i++) {
    mt[i].getMinimumResolution = function() {return 1;}
    mt[i].getMaximumResolution = function() {return 18;}
  }  
} //function setZoomLimits

function submitListForm() {
 new Ajax.Updater('result_list', map_contents_route, {asynchronous:true, evalScripts:false, parameters:Form.serialize($('listMapContentFrm'))}); 
 return false; 
} //function submitListForm

function setMapBounds() {
  bounds = map.getBounds()
  $('minLat').value = bounds.getSouthWest().lat();
  $('minLng').value = bounds.getSouthWest().lng();
  $('maxLat').value = bounds.getNorthEast().lat();
  $('maxLng').value = bounds.getNorthEast().lng();  
} // function setMapBounds

function refreshPoints(setbounds) {
  Element.show('mapindicator');
  anyItems = false;
  var minLat = $('minLat').value;
  var minLng = $('minLng').value;
  var maxLat = $('maxLat').value;
  var maxLng = $('maxLng').value;
  var itemTypes = document.getElementsByName('itemType[]');
  typeArr = [];
  for (var i = 0; i < itemTypes.length; i++) {
    if ( itemTypes[i].checked ) {
      typeArr.push(itemTypes[i].value);
    }   
  }
  var typeString = typeArr.join(',');
  var myUrl = bounds_url + "/minLat/" + minLat + 
                           "/minLng/" + minLng + 
                           "/maxLat/" + maxLat + 
                           "/maxLng/" + maxLng + 
                           "/itemType/" + typeString + "/";
  if ( join_query ) {
  	myUrl += "join_query/" + join_query + "/";
  }
	var request = GXmlHttp.create();
	request.open("GET", myUrl, true);
	request.onreadystatechange = function() {
    if (request.readyState == 4) {
      var rtnXML = GXml.parse(request.responseText);
      var level = rtnXML.documentElement.getElementsByTagName("LEVEL")[0].childNodes[0].nodeValue;
      latestBatch = {};
      if (level == 'point') {
        showPoints(rtnXML);
      } else if (level == 'city') {
        showClusters(rtnXML, 'city');
      } else if (level == 'state') {
        showClusters(rtnXML, 'state');
      } else if (level == 'country') {
        showClusters(rtnXML, 'country');        
      } else if (level == 'max') {
        $('infoArea').innerHTML = "There are too many items to display. Please zoom in to see details."; 
        anyItems = true;
      }
      cleanUpMarkers();
      displayedMarkers = latestBatch;
      if ( setbounds ) {
      	zoomToIncludeAllMarkers(displayedMarkers);
      }
      if ( !anyItems ) {
        $('infoArea').innerHTML = "There are no items to display at this location. Try zooming out to see items.";
      }
      Element.hide('mapindicator');
    }
	};
	request.send(null);	
} //function refreshPoints

function showPoints(xml) {
  var points = xml.documentElement.getElementsByTagName("POINT");
  for (var i = 0; i < points.length; i++) {
    var pointInfo = loadXMLAssociativeArray(points[i]);
    var pt = new GLatLng(pointInfo["LATITUDE"], pointInfo["LONGITUDE"]);
    var ptStr = "ptCluster-" + pt.lat() + "," + pt.lng();
    if ( !displayedMarkers[pointInfo["MASTERID"]] ) {
      var clusterText = '<a target="_blank" href="' + pointInfo["URL"] + '">' + unescape(pointInfo["NAME"]) + '</a>';
      if ( dupePoints[ptStr] ) {
        var marker = processDupePoint(pt, ptStr);
        latestBatch[ptStr] = marker;
      } else {
        var marker = createMarker(pt, pointInfo["MASTERID"], pointInfo["TYPE"], pointInfo["URL"], pointInfo["ADDRESS"]);
        clusterer.AddMarker(marker, clusterText);
        dupePoints[ptStr] = {};
        latestBatch[pointInfo["MASTERID"]] = marker;
      }
      var dupePointTitle ='<img src="../../../images/map/' + pointInfo["TYPE"] + '_marker.png" width="6" height="10">&nbsp;' + clusterText; 
      dupePoints[ptStr][pointInfo["MASTERID"]] = { Title: dupePointTitle,
      											   Type: pointInfo["TYPE"] }; 
    } else {
      var marker = displayedMarkers[pointInfo["MASTERID"]];
      latestBatch[pointInfo["MASTERID"]] = marker;
    } 
    anyItems = true;     
  }
  cleanUpDupePoints();
  $('infoArea').innerHTML = "Click on an individual item marker or an item cluster (<img src='../../../images/map/markercluster.png' width='26' height='21px' />) for details.";
} //function showPoints

function cleanUpDupePoints() {
  for (i in dupePoints) {
    if (!dupes[i]) {
      delete dupePoints[i];
    }
  } 
} //function cleanUpDupePoints

function processDupePoint(pt, ptStr) {
  if ( !latestBatch[ptStr] && !displayedMarkers[ptStr]) { //the cluster marker hasn't been created yet, so create it
    for (i in dupePoints[ptStr]) { //get the ID for the point marker that we need to replace with the cluster marker
      var firstMarkerID = i;
      break;
    }
    if ( latestBatch[i] ) { //if the point was created in the latest batch, then remove it from there
      clusterer.RemoveMarker(latestBatch[i]);
      delete latestBatch[i];
    }
    if ( displayedMarkers[i] ) { //if the point was created in a previous batch, then remove it from there
      clusterer.RemoveMarker(displayedMarkers[i]);
      delete displayedMarkers[i];
    }
    //create the cluster marker
    var marker = new GMarker(pt, {icon: fixedSizeClusterIcon(), draggable: false});
    dupes[ptStr] = 1;
    dupePointListener(marker, ptStr);
    map.addOverlay(marker);
    return marker;
  } else {
    return ( latestBatch[ptStr] ) ? latestBatch[ptStr] : displayedMarkers[ptStr];
  }  
} //function processDupePoint

function dupePointListener(marker, ptStr) {
  GEvent.addListener(marker, "click", function() {
    var text = '';
    var ctr = 0;
    var remainderCtr = 0;
    for (i in dupePoints[ptStr]) {
      if ( typeArr.indexOf(dupePoints[ptStr][i].Type) != -1 ) {
	    ctr++;
	    if ( ctr > clusterTitleMax ) {
	      remainderCtr++;
	    } else {
	      text += dupePoints[ptStr][i].Title + '<br />';
	    }
      }
    }
    if (remainderCtr > 0) {
      text += "...and " + remainderCtr + " more";
    }
    marker.openInfoWindowHtml(text);  
  });  
} //function dupePointListener

function cleanUpMarkers() {
  for (var i in displayedMarkers) {
    if ( !latestBatch[i] ) {
      clusterer.RemoveMarker(displayedMarkers[i]);
      map.removeOverlay(displayedMarkers[i]);
      delete dupes[i];
      delete dupePoints[i];
      delete displayedMarkers[i];
    }    
  }
} //function cleanUpMarkers

function showClusters(xml, level) {
  var points = xml.documentElement.getElementsByTagName("CLUSTER");
  var total = xml.documentElement.getElementsByTagName("TOTAL")[0].childNodes[0].nodeValue;
  var count = xml.documentElement.getElementsByTagName("CLUSTERCOUNT")[0].childNodes[0].nodeValue;
  var avg = parseFloat(total)/parseFloat(count);
  for (var i = 0; i < points.length; i++) {
    var pointInfo = loadXMLAssociativeArray(points[i]);
    var pt = new GLatLng(pointInfo["LATITUDE"], pointInfo["LONGITUDE"]);
    var markerID = pointInfo["NAME"];
    clusterCounts[pointInfo["NAME"]] = parseFloat(pointInfo["COUNT"]);
    if ( displayedMarkers[markerID] ) {
      map.removeOverlay(displayedMarkers[markerID]);
    }
    var marker = createClusterMarker(pt, pointInfo["NAME"], pointInfo["COUNT"], avg);   
    map.addOverlay(marker);
    latestBatch[markerID] = marker;
    anyItems = true;
  }
  $('infoArea').innerHTML = "There are too many items to display. Items have been grouped by " +
                          level + " (<img src='../../../images/map/cluster.png' height='25px'/>). Zoom in to see more detail.";
  
} //function showClusters

function validateItemType(chk) {
  checked = false;
  var itemTypes = document.getElementsByName('itemType[]');
  for (var i = 0; i < itemTypes.length; i++) {
    if ( itemTypes[i].checked ) {
      checked = true
    }   
  }
//  if (!checked) {
//    chk.checked = true;
//    alert('At least 1 item type must be selected');
//  } else {
    startSelected = true;
    if ( listContents ) {
      submitListForm();
    }
    refreshPoints(false);
//  }
} //function validateItemType

function createMarker(pt, masterid, itemType, url, address) {
  var marker = new GMarker(pt, {icon:pointIcon(itemType), draggable: false});
  GEvent.addListener(marker, "click", function() {
    var ent_name = getEntityName(masterid, itemType);
    marker.openInfoWindowHtml("<a target='_blank' href='" + url + "'>" + ent_name + "</a><br />" + address);  
  });
  return marker;
} //function createMarker

function getEntityName(masterid, itemType) {
  var myUrl = ent_name_url + "/masterid/" + masterid + "/type/" + itemType;
	var request = GXmlHttp.create();
	request.open("GET", myUrl, false);
	request.send(null);
  if (request.readyState == 4) {
    var rtnXML = GXml.parse(request.responseText);
    var ent_name = rtnXML.documentElement.getElementsByTagName("ENTITY")[0].childNodes[0].firstChild.nodeValue;
  }
  return ent_name;
} //function getEntityName

function pointIcon(itemType) {
	var f = new GIcon();
	f.image = "../../../images/map/" + itemType + "_marker.png";
	f.shadow = "../../../images/map/point_s.png";
  f.iconSize = new GSize(12,20);
  f.shadowSize = new GSize(22,20);
  f.iconAnchor = new GPoint(6,20);
  f.infoWindowAnchor = new GPoint(6,1);
  f.infoShadowAnchor = new GPoint(13,13);
	
	return f;
} //function pointIcon

function clusterIcon(pct) {
  var clusterIcon = new GIcon();
  clusterIcon.image = '../../../images/map/cluster.png';
  var baseWidth = 15;
  var baseHeight = 25;
  var baseIconAnchorWidth = 6;
  var baseIconAnchorHeight = 25;
  var baseInfoWindowAnchorWidth = 13;
  var baseInfoWindowAnchorHeight = 3;
  var baseInfoShadowAnchorWidth = 27;
  var baseInfoShadowAnchorHeight = 37;  
  var width = baseWidth * pct;
  var height = baseHeight * pct;
  var iconAnchorWidth = baseIconAnchorWidth * pct;
  var iconAnchorHeight = baseIconAnchorHeight * pct;
  var infoWindowAnchorWidth = baseInfoWindowAnchorWidth * pct;
  var infoWindowAnchorHeight = baseInfoWindowAnchorHeight * pct;
  var infoShadowAnchorWidth = baseInfoShadowAnchorWidth * pct;
  var infoShadowAnchorHeight = baseInfoShadowAnchorHeight * pct; 
  if ( width < 5 ) {
    width = baseWidth/2;
    height = baseHeight/2;
    iconAnchorWidth = baseIconAnchorWidth/2;
    iconAnchorHeight = baseIconAnchorHeight/2;
    infoWindowAnchorWidth = baseInfoWindowAnchorWidth/2;
    infoWindowAnchorHeight = baseInfoWindowAnchorHeight/2;
    infoShadowAnchorWidth = baseInfoShadowAnchorWidth/2;
    infoShadowAnchorHeight = baseInfoShadowAnchorHeight/2; 
  }
  clusterIcon.iconSize = new GSize( width, height );
  clusterIcon.iconAnchor = new GPoint( iconAnchorWidth, iconAnchorHeight );
  clusterIcon.infoWindowAnchor = new GPoint( infoWindowAnchorWidth, infoWindowAnchorHeight );
  clusterIcon.infoShadowAnchor = new GPoint( infoShadowAnchorWidth, infoShadowAnchorHeight );
  
	return clusterIcon;
} //function clusterIcon

function fixedSizeClusterIcon() {
  var clusterIcon = new GIcon();
  clusterIcon.image = '../../../images/map/markercluster.png';
  clusterIcon.iconSize = new GSize( 26, 21 );
  clusterIcon.iconAnchor = new GPoint( 13, 24 );
  clusterIcon.infoWindowAnchor = new GPoint( 13, 3 );
  clusterIcon.infoShadowAnchor = new GPoint( 27, 37 );
  
	return clusterIcon;
} //function clusterIcon

function createClusterMarker(pt, clusterName, pt_count, avg) {
  var ratio = pt_count/avg;
  if ( ratio <= .4 ) {
    var pct = .25;
  } else if ( ratio > .4 && ratio <= .8 ) {
    var pct = .5;
  } else if ( ratio > .8 && ratio <= 1.2 ) {
    var pct = .75;
  } else if ( ratio > 1.2 && ratio <= 3 ) {
    var pct = 1;
  } else if ( ratio > 3 && ratio <= 4 ) {
    var pct = 1.25;
  } else {
    var pct = 1.5;
  }
  
  var marker = new GMarker(pt, {icon: clusterIcon(pct),draggable: false, title: clusterName});
  clusterMarkerListeners(marker, clusterName);
  return marker;
} //function createClusterMarker

function clusterMarkerListeners(marker, clusterName) {
  GEvent.addListener(marker, "click", function() {
//    map.panTo(marker.getPoint());
    var clusterCount = getClusterCount(clusterName);
    marker.openInfoWindowHtml(clusterName + "<br />" + clusterCount + " Item(s) <br />" +
                              "<a href='javascript:map.setCenter(new GLatLng" + marker.getPoint() + ");map.zoomIn();map.closeInfoWindow();'>Zoom in </a>");
  });  
} //function clusterMarkerInfoWindow

function getClusterCount(clusterName) {
  return clusterCounts[clusterName];
} //function getClusterCount

function zoomToIncludeAllMarkers(markers) {
  var bounds = new GLatLngBounds();
  for (var i in markers) {
    bounds.extend(markers[i].getPoint());
  }	
  map.setZoom(map.getBoundsZoomLevel(bounds));
  map.setCenter(bounds.getCenter());
}

function loadXMLAssociativeArray(xmlObj) {
	var attrArray = {};
	var children =  xmlObj.childNodes;
	for (var i = 0; i < children.length; i++) {
		if (children[i].nodeType == 1) {
			if (children[i].hasChildNodes()) {
				var value = children[i].firstChild.nodeValue;
			} else {
				var value = "";
			}
			attrArray[children[i].nodeName] = value;
		}
	}
	return attrArray;
} //function loadXMLAssociativeArray

function goToAddress(address) {
  if (address.length > 0) {
    var geocoder = new GClientGeocoder();

    geocoder.getLatLng(address,
      function(point) {
        if (!point) {
          alert('Address "' + address + '" not found');
        } else {
          map.setCenter(point, 13);
        }
      });
  }
} //function centerMap

var fldClicked = false;
function clearText(fld) {
	if (! fldClicked) {
		fld.value = "";
		fldClicked = true;
	}
} //function clearText