  google.load("maps", "2.x");
  var map = '';
  var effortoverlay = '';

  function clearEffortOverlay() {
    if (effortoverlay != '') {
      map.removeOverlay(effortoverlay);
      effortoverlay = '';
    }
  }

  function clearAllOverlays() {
    clearEffortOverlay();
    // Clear all the others
    map.clearOverlays();
  }


  function mapcatches(catchrecords) {
    for (i in catchrecords) {
      drawicon(catchrecords[i]);
    }
  }

  function drawicon(catchrecord) {
    var catchloc = new GLatLng(catchrecord.latitude, catchrecord.longitude);
    var catchicon = new GIcon(G_DEFAULT_ICON); 
    catchicon.image = catchrecord.icon;
    var markeroptions = {
      title:catchrecord.barcode,
      icon:catchicon
    };
    var catchmarker = new GMarker(catchloc, markeroptions); 
    var temperature = "";
    if (catchrecord.temperature_c != null) {
      temperature = catchrecord.temperature_c + " degrees Celsius<br>";
    }
    var timestr = catchrecord.timestamp.toLocaleDateString()
    var infohtml = '<div style="color:black; width: 320px;">' 
                 + '<table>' 
                 + "<tr><td>Fisherman:</td><td>" + catchrecord.first_name + " " + catchrecord.last_name + "</td>"
			 + '<td width="100" rowspan="5" valign="top"><img src="/images/fishermen/'+catchrecord.fisherman_code+'.jpg"></td></tr>'
                 + "<tr><td><nobr>Date of Catch</nobr>:</td><td>" + timestr + "</td></tr>"
                 + "<tr><td>Vessel:</td><td>" + catchrecord.vessel + "</td></tr>"
                 + "<tr><td valign='top'>River System:</td><td>"
			 + catchrecord.source_stock + "</td></tr>"
                 + "</table></div>"

/*
                 + '<div>' 
                 + "Fisherman: " + catchrecord.fisherman_code
                 + "</div>" 
                 + "Date of Catch: " + timestr 
                 + "<br>"  
                 + "Water Temp: " + temperature 
                 + "Name of Boat: " + "<br>"
                 + "River of Origin: "
                 + catchrecord.source_stock + " (" + Math.round(100*catchrecord.confidence,2) + "% confidence)"
                 + "<br></div>"
*/

    catchmarker.bindInfoWindowHtml(infohtml);
    map.addOverlay(catchmarker);
    catchmarker.openInfoWindow(infohtml); // TODO what do you pass in here?
  }

  function showCatch() {
    // get the metadata for the given barcode
    // and display it on the map
    var code = JQ('#barcode').attr('value')
    PF.FGet("CROOSFishCatchByBarcode", "JSONRecords", mapcatches); 
  }

  function showcatchoverlay() {
    var month = JQ("#CROOSCatchMonth").val();
    showeffort(month,'catches');
  }

  function showeffortoverlay() {
    var month = JQ("#CROOSEffortMonth").val();
    showeffort(month,'effort');
  }


  function showeffort(month,source) {
    clearEffortOverlay();

    var effortTileLayer = new GTileLayer(new GCopyrightCollection(""), 1, 22);

    effortTileLayer.getTileUrl = function(tile, zoom) {
      var proj = G_NORMAL_MAP.getProjection(); 
      var bins = 50;
      var se = proj.fromPixelToLatLng(new GPoint(tile.x*256,tile.y*256),zoom)
      var nw = proj.fromPixelToLatLng(new GPoint((tile.x+1)*256,(tile.y+1)*256),zoom) 
      var xmin = se.lng();
      var xmax = nw.lng();
      var ymin = nw.lat();
      var ymax = se.lat();
      var url = "http://www.pacificfishtrax.org/pyrview/index.py/getcachedproduct?usecache=&product=CROOSEffortMap&data_source="+source+"&month="+month+"&bins="+bins+"&axesoff=True&xlimits="+xmin+"%2C"+xmax+"&ylimits="+ymin+"%2C"+ymax;

      //JQ("body").append(url + "<br>");
      return url;
    };

    var tileLayerOverlay = new GTileLayerOverlay(effortTileLayer);
    map.addOverlay(tileLayerOverlay);
    tileLayerOverlay.show();

    // keep track of current overlay so we only show one at a time.
    effortoverlay = tileLayerOverlay;

  };

  function showTrack() {
    // get the tracklog for this fisherman code

    var drawline = function(polyline) {
      var polyline = new GPolyline(polyline, "#ff0000", 7);
      map.addOverlay(polyline);
    }
    PF.FGet("CROOSTracklogByCodeAndMonth", "GMapLatLon", drawline); 
  }

  function showCatches() {
    // Get all catches for this fisherman code
    var code = JQ(this).attr('value')
    PF.FGet("CROOSFishCatchByFishermanCodeAndMonth", "JSONRecords", mapcatches); 
  }

  // Call this function when the page has been loaded
  function initialize() {
    map = new google.maps.Map2(document.getElementById("map"), 
        { size: new GSize(400,640) } );
    map.addControl(new GSmallMapControl());
    map.setCenter(new google.maps.LatLng(44.27, -125.1), 7);
    map.setMapType(G_HYBRID_MAP);

    // Set up the barcode handling stuff
    JQ("#barcodesubmit").bind("click", showCatch);

    // Set up the Aggregate Effort stuff
    JQ("#mapeffortoverlay").bind("click", showeffortoverlay);

    // Set up the Catch overlay
    JQ("#mapcatchoverlay").bind("click", showcatchoverlay);

    // Set up the Tracklog display
    JQ("#mapfishermandata").bind("click", showTrack);

    // Set up the Tracklog display
    JQ("#mapfishermandata").bind("click", showCatches);

    // Set up the clearAll link
    JQ("#clearall").bind("click", clearAllOverlays);

    // Enter key does the same thing as clicking the button
    JQ("#barcodeField").keyup(function(e){
      // alert(e.keyCode);
      if(e.keyCode == 13) {
        showCatch();
	JQ(this).val("");
      }
    });
  }
  google.setOnLoadCallback(initialize);
