/* Create a new OpenLayers map with sensible default options and a baselayer.
*
* Parameters:
* mapId - {String} the ID of the DOM element to turn into a map
* openLayersOptions - {Object} hash of options passed into OpenLayers.Map
*     constructor (optional)
* options - {Object} additional options (optional)
*      disableZoomWheel: {Boolean} if true, map zooming via the scroll wheel
*        will be disabled
*      enablePopups: {Boolean} if true, clicking on features will open a popup
*      features: features to put on map
*
* Returns:
* {OpenLayers.Map} the new map object
*/
function createMap(mapId, openLayersOptions, options) {
  var options = options ? options : {};
  var bounds = new OpenLayers.Bounds(
    -2.003750834E7,-2.003750834E7,
    2.003750834E7,2.003750834E7
  );
  var defaultOptions = {
    projection: new OpenLayers.Projection('EPSG:900913'),
    maxExtent: bounds,
    maxResolution: 156543.03390625,
    format: 'img/png'
  };
  openLayersOptions = jQuery.extend(true, defaultOptions, openLayersOptions);
  var map = new OpenLayers.Map(mapId, openLayersOptions);    

  // Add basic map layer, i.e., streets, etc
  /*var streetLayer = new OpenLayers.Layer.WMS(
      'OpenStreetMap',
      'http://demo.opengeo.org/geoserver_openstreetmap/gwc/service/wms',
      {
          layers: 'openstreetmap',
          format: 'image/png',
      },
      {
          transitionEffect: 'resize',
      }
  );*/
  var streetLayer = new OpenLayers.Layer.Google('streets', {numZoomLevels: 20, sphericalMercator: true});
  map.addLayer(streetLayer);

  var style = new OpenLayers.Style({
	    		             externalGraphic: "${bunchIcon}", //single flower or a bunch?
		  	             graphicWidth: "${bunchWidth}", //set size for flower/bunch
			             graphicHeight: "${bunchHeight}", //height for flower/bunch
			             backgroundGraphic: "${bunchBackground}", //shadow is different for the two icons
				     graphicYOffset: "${yoffset}",
				     graphicXOffset: "${xoffset}",
	                             backgroundYOffset: "${backyoffset}",
	                             backgroundXOffset: "${backxoffset}",
	                             graphicZIndex: 11,
	                             backgroundGraphicZIndex: 10
				   },
			           {
			             context: {
			               bunchIcon: function(feature) {
			                 var pix = "/icons/yellow_flower.png";
			                 if (feature.attributes.count > 1) { //if there is more than one, it's a cluster
			                   pix = "/icons/flower_clump.png";
			                 }
			                 return pix;
			               }, //there might be a more efficient way to set these context parameters all at once.
			               bunchWidth: function(feature) {
			                 var width = 46;
			                 if (feature.attributes.count > 1) {
			                   width = 50; //bunch icon is wider
			                 }
			                 return width;
			               },
			               bunchHeight: function(feature) {
			                 var height = 47;
			                 if (feature.attributes.count > 1) {
			                   height = 37; //bunch icon is smaller
			                 }
			                 return height;
			               },
			               bunchBackground: function(feature) {
			                 var shadow = "/icons/flower_shadow.png";
			                 if (feature.attributes.count > 1) { //need the bunch
			                   shadow = "/icons/flower_clump_shadow.png";
			                 }
			                 return shadow;
			               },
			               yoffset: function(feature) {
			                 var offset = -48;
			                 if (feature.attributes.count > 1) { //if there is more than one, it's a cluster
			                   offset = -15;
			                 }
			                 return offset;
			               }, //there might be a more efficient way to set these context parameters all at once.
			               xoffset: function(feature) {
			                 var offset = -21;
			                 if (feature.attributes.count > 1) {
			                   offset = -21;
			                 }
			                 return offset;
			               },
			               backyoffset: function(feature) {
			                 var offset = -48;
			                 if (feature.attributes.count > 1) {
			                   offset = -15;
			                 }
			                 return offset;
			               },
			               backxoffset: function(feature) {
			                 var offset = -12;
			                 if (feature.attributes.count > 1) { //need the bunch
			                   offset = -12;
			                 }
			                 return offset;
			               }
			             }
			           });

  strategy = new OpenLayers.Strategy.Cluster();
  //how close parties can be before the cluster kicks in
  strategy.distance = 50;

  var features = options['features'];
  var clusterfeatures = [];
  selectedfeature = [];

  for (var i=0; i<features.length; i++) {
    var lonlat = new OpenLayers.LonLat(features[i][2],features[i][1]);
    var lonlatClone = lonlat.clone().transform(new OpenLayers.Projection('EPSG:4326'), new OpenLayers.Projection('EPSG:900913'));
    var marker = new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlatClone.lon, lonlatClone.lat));
    marker.attributes.description = decodeURIComponent(features[i][3]);
    clusterfeatures.push(marker);
  }

  clusters = new OpenLayers.Layer.Vector("Clusters", {
                                           projection: new OpenLayers.Projection('EPSG:4326'),
                                           rendererOptions: {yOrdering: true},
                                           strategies: [strategy],
                                           styleMap: new OpenLayers.StyleMap(style)
                                         });	
  clusters.addFeatures(clusterfeatures);
  map.addLayer(clusters);

  if (clusterfeatures.length < 1) {
    // Center on 349 West 12th St. by default
    var center = new OpenLayers.LonLat(-74.006952, 40.738067);
    center.transform(new OpenLayers.Projection('EPSG:4326'), map.getProjectionObject());
    map.setCenter(center, 12); 
  } else {
    map.zoomToExtent(clusters.getDataExtent());
  }

  clusters.removeFeatures(clusters.features); 
  clusters.addFeatures(clusterfeatures);

  if (options['disableZoomWheel']) {
    var navControl = map.getControlsByClass('OpenLayers.Control.Navigation')[0];
    if (navControl) {
      navControl.disableZoomWheel();
    }
  }

  if (options['enablePopups']) {
    function onSelectFeature(feature) {
      if (selectedfeature.popup) 
        onUnselectFeature(selectedfeature);

      if (feature.cluster.length > 1) {
        map.setCenter(new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y));
        map.zoomIn();
        return;
      }

      selectedfeature = feature;
      var popup = new OpenLayers.Popup.FramedCloud(null, feature.geometry.getBounds().getCenterLonLat(),
                                                   null, feature.cluster[0].attributes.description,
                                                   {size: new OpenLayers.Size(1, 1), offset: new OpenLayers.Pixel(1,-32)},
                                                   true, function() { selectControl.unselect(feature); });
      feature.popup = popup
      map.addPopup(popup);
    }

    function onUnselectFeature(feature) {
      if (!feature.popup) return;
      map.removePopup(feature.popup);
      feature.popup.destroy();
      feature.popup = null;
    }

    var clusters = map.getLayersByName('Clusters')[0];
    if (clusters) {
      var selectControl = new OpenLayers.Control.SelectFeature(clusters,
        {onSelect: onSelectFeature, onUnselect: onUnselectFeature});
      map.addControl(selectControl);
      selectControl.activate();
    }
  }

 
  return map;
}

