// Create the InventiveLabs namespace if necessary.
var IL = IL || {};

// Define the GMap controller class.
IL.GMap = {
  /*
    Points given to this function should look like:
    {
      lat: x,
      lng: y,
      rank: f,
      dataId: 'id'
    }
    
    Lines given to this function should look like:
    {
      lat1: x1,
      lng1: y1,
      lat2: x2,
      lng2: y2
    }

    Available options are:
      small - boolean for using small or large (ie, with zoom slider) controls 
      zoomLevel
      centerLat
      centerLng
      mapType
      lineWidth - pixels
      
  */
  load: function(mapId, points, lines, options) {
    if (!GBrowserIsCompatible()) { return null; }

    // set default options if any options not specified.
    options = options || {};
    options.small = options.small || false;
    options.zoomLevel = options.zoomLevel || mapZoom || 12;
    options.centerLat = points.first().lat;
    options.centerLng = points.first().lng;
    options.mapType = options.mapType || "Map";    
    options.lineWidth = options.lineWidth || 3;
    options.lineOpacity = options.lineOpacity || 1.0;    

    // create map & map controls
    var _map = new GMap2($(mapId));
    _map.setCenter(
      new GLatLng(options.centerLat, options.centerLng), 
      options.zoomLevel
    );
    IL.GMap.setMapTypeByName(_map, options.mapType);
    _map.addControl(
      options.small ? new GSmallMapControl() : new GLargeMapControl()
    );
    _map.enableScrollWheelZoom();
    _map.enableContinuousZoom();

    // add the points
    _map.markers = $A();
    points.each(function (pt) {
      _map.markers.push(IL.GMap.addPointToMap(_map, pt));
    });
    
    // add the lines
    _map.lines = $A();
    lines.each(function (line) { 
      _map.lines.push(IL.GMap.addLineToMap(_map, line, 3, 1.0)); 
    });

    // Path functions for this map.
    _map.path = function () {
      return _map.markers.select(
        function (mkr) {return !!mkr.rank;}
      ).sortBy(
        function (mkr) {return parseFloat(mkr.rank);}
      );
    }
    _map.orphans = function () {
      return _map.markers.select( function (mkr) {return !mkr.rank;} );
    }
     
    // Add trail buttons to bottom-right corner of map
    if (_map.path().length > 0 && !options.no_trail_buttons) {
      _map.addControl(
        new PathFirstControl(),
        new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(36, 4))
      );
      _map.addControl(
        new PathNextControl(),
        new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(4, 4))
      );
    }

    // open the first infowindow
    var firstMarker = _map.path().find(function (mkr) { return !mkr.kink() });
    if (firstMarker) { 
      firstMarker.openInfoWindow(firstMarker.infWin); 
      _map.setCenter(firstMarker.getLatLng(), options.zoomLevel);
    }
    
    // Set map bounds if requested
    if (options.size_to_fit) {
      var bounds = _map.markers.inject(null, function (acc,mkr) {
        var pt = mkr.getPoint();
        if (!acc) {
          acc = { n: pt.lat(), s: pt.lat(), e: pt.lng(), w: pt.lng() }
        } else { 
          acc.n = Math.min(acc.n, pt.lat());
          acc.s = Math.max(acc.s, pt.lat());
          acc.w = Math.min(acc.w, pt.lng());
          acc.e = Math.max(acc.e, pt.lng());
        }
        return acc;
      });
      var gBounds = new GLatLngBounds(
        new GLatLng(bounds.s, bounds.w), 
        new GLatLng(bounds.n, bounds.e)
      );
      _map.setCenter(gBounds.getCenter(), _map.getBoundsZoomLevel(gBounds));
    }

    return _map;
  },

  addPointToMap: function(map, point) {
    var marker = new GMarker(new GLatLng(point.lat, point.lng), point.icon);
    marker.rank = point.rank;
    marker.kink = function () { return false; }
    map.addOverlay(marker);
    marker.infWin = $(point.dataId);
    marker.bindInfoWindowHtml(marker.infWin);
    GEvent.addListener(marker, 'infowindowopen', function () {
      map.activeMarker = marker;
    });
    return marker;
  },
  
  addLineToMap: function(map, line, width, opacity) {
    var polyline = new GPolyline(
      [
        new GLatLng(line.lat1, line.lng1), 
        new GLatLng(line.lat2, line.lng2)
      ],
      getPathColour(line.pathId), 
      width, 
      opacity
    );
    map.addOverlay(polyline);
    return polyline;
  },

  setMapTypeByName: function(map, name) {
    var mtypes = map.getMapTypes();
    mtypes.each(
      function (mtype) {if (mtype.getName() == name) {map.setMapType(mtype);}}
    );
  }
}

function getPathColour(pathId) {
  window.pathColours = window.pathColours || $H();
  if (window.pathColours.get(pathId)) { return window.pathColours.get(pathId); }

  var clr = null, cursor;
  if ((cursor = window.pathColours.size()) < 7) {
    clr = ["#F11", "#F90", "#509", "#009", "#090", "#09F", "#950"][cursor];
  } else {
    var dice = function () { 
      return "0123456789ABCDEF".substr(parseInt(Math.random() * 16), 1)
    }
    clr = "#" + dice() + dice() + dice();
  }
  window.pathColours.set(pathId, clr); 
  return clr;
}
