
// define a global variable for the map (so any function can access it)
var map;

function init() {
  // don't even try to work if this is crazy old browser
  if (!GBrowserIsCompatible()) {
	  return;
  }
	
	// create the map
  map = new GMap2(document.getElementById("map"));
	
	// set where the map starts
	var centerLatitude = 41.0;
	var centerLongitude = -73.0;
	var startZoom = 8;
  map.setCenter(new GLatLng(centerLatitude, centerLongitude), startZoom);
	
	// initialize features on the map
  map.setMapType(G_SATELLITE_MAP);
  map.addControl(new GSmallMapControl());
  map.addControl(new GMapTypeControl());
  map.enableScrollWheelZoom();
  
	// add a click listener
	function onClickCallback(marker, latlng) {
    if (marker) {
      // do nothing - this is necessary because sometimes gmaps fires extra events
    } else {
			// update the little white lat/long
      document.getElementById("message").innerHTML = latlng.toString();
			// create the input form
      map.openInfoWindowHtml(latlng,
        "<form onsubmit='storeMarker(); return false;'>" +
          "<input type=hidden name=lat id=lat value='" + latlng.lat() + "'/>" +
          "<input type=hidden name=lng id=lng value='" + latlng.lng() + "'/>" +
          "name: <input type=text size=8 name=name id=name /><br>" +
          "tags: <input type=text size=8 name=tags id=tags /><br>" +
          "description: <input type=text size=8 name=description id=description /><br>" +
		      "<input type=submit />" +
        "</form>"
      );
    }
	}
  GEvent.addListener(map, "click", onClickCallback);
	
  // get markers from server
  var request = GXmlHttp.create();
  request.open('GET', 'retrieveMarkers.php', true);
	// event handler function - when the request is finished, it will be called
	function drawMarkers() {
		// "4" is the magic constant that means "done"
    if (request.readyState == 4) {
      // request.responseText is a JSON formatted string of the form:
      // [ { lat: 1, lng: 2, name: 'a', ... }, {...}, ... ]
      var response = eval(request.responseText);
			// show all the markers on the map
      // this is a for-loop: for (start condition; end condition; step function) { looped stuff }
      for (var index = 0; index < response.length; index = index + 1) {
				// this takes the object in the index position of the response array and assigns it to be point
        var point = response[index];
        addPoint(point);
      }
      // after all the points have been added to memory, we init the UI
      initLegend();
    }
  }
  request.onreadystatechange = drawMarkers;
  request.send(null);
}

function storeMarker() {
	//pulls what people type in the form into javascript variables
	var p = {};
  p.lat = document.getElementById("lat").value;
  p.lng = document.getElementById("lng").value;
  p.name = document.getElementById("name").value;
  p.tags = document.getElementById("tags").value;
  p.description = document.getElementById("description").value;
  
	// URL parameters to storeMarker.php must be in the form "?name=foo&param=value"
	//concatenates all the parameters into something that the server can read
  var serverParams = "?"
    + "&name=" + p.name
    + "&lat=" + p.lat
    + "&lng=" + p.lng
		+ "&tags=" + p.tags
		+ "&description=" + p.description;
  
  // request to storeMarker.php on your server
  var request = GXmlHttp.create();
  request.open('GET', 'storeMarker.php' + serverParams, true);
	// this is sending the form inputs to the server
  request.send(null);
	
	// draw the new marker on the map (this assumes that storeMarker.php will always succeed)
	addPoint(p);
	map.closeInfoWindow();
	
	// since there might be a new tag, re-create the legend
	initLegend();
}

// the browser will use this empty array to store the points from the database that retrieveMarker returned
var points = [];

// take our custom data structure of a point as an input parameter and make a GMaps marker out of it
function addPoint(point) {
  // first, upgrade a point so that it has at least one tag
  if (!point.tags) {
    point.tags = 'untagged';
  }
  
  // then add to the map
  createMarker(point);

  // now add the point to the end of the above declared array which we can use later
  points.push(point);
}

// create a labeled marker from a point and put it on the map
function createMarker(point, hovered) {
  var latlng = new GLatLng(parseFloat(point.lat), parseFloat(point.lng));
  var icon = new GIcon();
  icon.image = 'automarker.png';
  // icon.image = hovered ? 'rollovermarker.png' : 'automarker.png';
  icon.iconSize = new GSize(108, 29);
  icon.iconAnchor = new GPoint(20, 0);
  icon.infoWindowAnchor = new GPoint(20, 28);
	
  var opts = { 
    "icon": icon,
    "clickable": true,
    "labelText": point.name,
    "labelOffset": new GSize(-17, 3)
  };
	if (hovered) {
		opts.zIndexProcess = function() { return 9*1000*1000 + 1; };
	}
  var marker = new LabeledMarker(latlng, opts);

  function showInfo() {
    marker.openInfoWindowHtml(
        "<b>name</b>: " + point.name + "<br>" +
        "<b>latitude</b>: " + point.lat + "<br>" +
        "<b>longitude</b>: " + point.lng + "<br>" +
        "<b>tags</b>: " + point.tags + "<br>" +
        "<b>description</b>: " + point.description + "<br>"
    );
  }
  GEvent.addListener(marker, 'click', showInfo);
	
	if (hovered) {
		GEvent.addListener(marker, "mouseout", function() {
			map.removeOverlay(marker);
			createMarker(point);
		});
	} else {
		GEvent.addListener(marker, "mouseover", function() {
			map.removeOverlay(marker);
			createMarker(point, true);
		});
	
		GEvent.addListener(marker, "mouseout", function() {
			marker.setImage('automarker.png');
		});
	}
  
  map.addOverlay(marker);
}

function updateMarkers() {
  map.clearOverlays();
  // try to add each point to the map
  for (var i = 0; i < points.length; i++) {
    var point = points[i];
    // if any tag is toggled on, show the point
    var showPoint = false;
    var pointTags = point.tags.split(' ');
    for (var j = 0; j < pointTags.length; j++) {
      var tag = pointTags[j];
      if (document.getElementById('toggle_' + tag).checked) {
        showPoint = true;
      }
    }
    if (showPoint) {
      createMarker(point);
    }
  }
}

// create (or re-create) the legend of tags
function initLegend() {
  var legend = document.getElementById('legend');
  // clear out old stuff
  legend.innerHTML = '';
  // find which tags we have (it's getting this from the array/memory structure that we made to store the points returned by retriveMarker.php). The goal of this object is to merge all the points' arrays of tags into one global list.
  var tags = {};
	//starting at index=0, going to the last available index and hitting every point along the way
  for (var i = 0; i < points.length; i++) {
		// square brackets are used to access objects in an array
		// here, var point is giving us the current point that the loop has reached
    var point = points[i];
		// point.tags means assume that point is a collection of sub-objects and try to find tags there. point.tags is a string.  javascript automagically gives all strings a split function.  split leaves the input string alone, and outputs an array of strings for the current point.
	  var pointTags = point.tags.split(' ');
		// loop over the tags.  pat made up the j part.
	  for (var j = 0; j < pointTags.length; j++) {
			// vat tag gives us the current tag that the loop has reached
	    var tag = pointTags[j];
			// if we have not already put this tag in our tag-storing-object, put it in now
	    if (!tags[tag]) {
				// the value we put here doesn't actually matter - we would have used an array to store the tags except the above line of code would have been a whole other nested for loop then. 
	      tags[tag] = true;
	    }
	  }
  }
  // loop through the tags and add them to the legend
  for (var key in tags) {
    // this hack is because we can't just use a for each loop in IE or safari
    if (!tags.hasOwnProperty(key)) {
      continue;
    }
    var div = document.createElement('div');
    div.innerHTML = '<input type="checkbox" checked="checked" id="toggle_' + key + '" ' +
        'onclick="updateMarkers();"/>' + key;
    legend.appendChild(div);
  }
}

window.onload = init;
window.onunload = GUnload;
