var _mMapError = "We are sorry, but we don\'t have maps at this zoom level for this region.Try zooming out for a broader look.";

// Add in mouse wheel based zooming :
GMap2.prototype.wheelZoom = function(event) { 
  if((event.detail || -event.wheelDelta) < 0)
    { map.zoomIn();} else { map.zoomOut();}
  return false;
}
 

function setupMapType(text, urlMethod, zoomStart, zoomEnd, copyrightText, hybrid) {

  var tileLayer = new GTileLayer(new GCopyrightCollection(copyrightText),zoomStart,zoomEnd);
  tileLayer.getTileUrl = urlMethod;
  tileLayer.getCopyright = function(a,b) {return copyrightText;}    
  var tileLayers = new Array();
  tileLayers[0] = tileLayer;

  if (hybrid) {
    tileLayers[1] = G_HYBRID_MAP.getTileLayers()[1];
  }

  var mt = new GMapType(tileLayers, G_SATELLITE_MAP.getProjection(), text,{errorMessage:_mMapError, maxResolution:zoomEnd, minResolution:zoomStart});      
  map.addMapType(mt);
  return mt;
}

function setupHybridMapType(text, urlMethods, zoomStart, zoomEnd, copyrightText) {
  // Setup a new map type with the default satellite layer, and the given layers on top.

  var tileLayers = [G_HYBRID_MAP.getTileLayers()[0]];  // Get the background default satellite layer
  for (var i=0;i <urlMethods.length;i++) {
    var tileLayer = new GTileLayer(new GCopyrightCollection(copyrightText),zoomStart,zoomEnd);
    tileLayer.getTileUrl = urlMethods[i];
    tileLayer.getCopyright = function(a,b) {return copyrightText;}    
    tileLayers[tileLayers.length] = tileLayer;
  }
  var mt = new GMapType(tileLayers, G_SATELLITE_MAP.getProjection(), text, {maxResolution:zoomEnd,minResolution:zoomStart,errorMessage:''});
  map.addMapType(mt);
  return mt;
}

function setupHybridMapType2(text, urlMethods, zoomStart, zoomEnd, copyrightText) {
  // Setup a new map type with the default satellite and map layer (Hybrid).  The new layers given go in between the default layers.

  var tileLayers = [G_HYBRID_MAP.getTileLayers()[0]]; // Get the background default satellite layer
  for (var i=0;i <urlMethods.length;i++) {
    var tileLayer = new GTileLayer(new GCopyrightCollection(copyrightText),zoomStart,zoomEnd);
    tileLayer.getTileUrl = urlMethods[i];
    tileLayer.getCopyright = function(a,b) {return copyrightText;}    
    tileLayers[tileLayers.length] = tileLayer;
  }
  tileLayers[tileLayers.length] = G_HYBRID_MAP.getTileLayers()[1]; // Add in the map layer on top
  var mt = new GMapType(tileLayers, G_SATELLITE_MAP.getProjection(), text, {maxResolution:zoomEnd,minResolution:zoomStart,errorMessage:''});
  map.addMapType(mt);
  return mt;
}

function getTileLatLon(x, y, zoom) {
  // Get the bottom right corner  lon, lat value and the width and height in lon lat
  var pi = 3.14159265;
  var lon      = -180; // x
  var lonWidth = 360; // width 360
  var lat = -1;
  var latHeight = 2;
  var tilesAtThisZoom = 1 << (17 - zoom);
  lonWidth  = 360.0 / tilesAtThisZoom;
  lon = -180 + (x * lonWidth);
  latHeight = -2.0 / tilesAtThisZoom;
  lat       = 1 + (y * latHeight);
  
  // convert lat and latHeight to degrees in a transverse mercator projection
  // note that in fact the coordinates go from about -85 to +85 not -90 to 90!
  latHeight += lat;
  latHeight = (2 * Math.atan(Math.exp(pi * latHeight))) - (pi / 2);
  latHeight *= (180 / pi);
  
  lat = (2 * Math.atan(Math.exp(pi * lat))) - (pi / 2);
  lat *= (180 / pi);

  latHeight -= lat;

  if (lonWidth < 0) {
    lon = lon + lonWidth;
    lonWidth = -lonWidth;
  }

  if (latHeight < 0) {
    lat += latHeight;
    latHeight = -latHeight;
  }
  
  return new Array(lon, lat, lonWidth, latHeight);
}

function getTileBox(x, y, zoom) {
  // Create a lat/lon box for this x/y and zoom level :
  res = getTileLatLon(x,y,zoom);
  var lon1 = res[0];
  var lon2 = res[0] + res[2];
  var lat1 = res[1];
  var lat2 = res[1] + res[3];
  return new Array(lon1, lat1, lon2, lat2);
}


function getCurrentCurrentLinkParams(isEmailFormat) {
    // Get parameters for a link that refers to the current page.
    // Encodes the parameters for email if needed

    var zoom = map.getZoom();
    var center = map.getCenter();
    var lat = center.y;
    var lon = center.x;
    var fgLayers = currentFGLayers.join(',');

    if (isEmailFormat)
        return 'lat=' + lat + '%26lon=' + lon + '%26zoom=' + zoom + '%26bg_layer=' + currentBGLayer + '%26fg_layers=' + fgLayers;
    else
        return 'lat=' + lat + '&lon=' + lon + '&zoom=' + zoom + '&bg_layer=' + currentBGLayer + '&fg_layers=' + fgLayers;
}

function setURLViewport() {
    // Set the lat, lon and zoom from the current url where possible.

    var q = getQueryString();

    var lat = q['lat'];
    var lon = q['lon'];
    if (typeof lat == 'undefined') lat = q['latitude'];
    if (typeof lon == 'undefined') lon = q['longitude'];

    if ((typeof lat != 'undefined') && (typeof lon != 'undefined')) {
        var position = new GLatLng(parseFloat(lat), parseFloat(lon));
        map.setCenter(position);
    }

    var zoom = q['zoom'];
    if (typeof zoom == 'undefined') zoom = q['z'];

    if (typeof zoom != 'undefined') {

        zoom = parseFloat(zoom);
        map.setZoom(zoom);
    }
}

function setupLayers(initialise) {
    // Set the month, and map overlay from the current url where possible.
    var q = getQueryString();
	
    var fg_layers = q['fg_layers'];
    if (fg_layers)
      fg_layers = fg_layers.split(',');
    if (!fg_layers)
      fg_layers = currentFGLayers;

    var bg_layer = q['bg_layer'];
    if (!bg_layer)
      bg_layer = currentBGLayer;

    if ((!initialise) && (fg_layers == currentFGLayers) && (bg_layer == currentBGLayer))
      return false; // Nothing changed.


    updateMapType(bg_layer, fg_layers);

    updateSelectors();

}

function updateSelectors() {
  // Make sure the selectors reflect the current variables.

  // Select the current background layer :
  id = 'backgroundLayerSelector';
  ob = document.getElementById(id);
  for (var i=0;i <ob.options.length;i++) {
    if (ob.options[i].value == currentBGLayer) {
      ob.selectedIndex = i;
      break;
    }
  }

  // Setup the foreground layer/s :
  for (var key in fgDefs) {
    var id = 'foregroundLayerSelector_' + key;
    var checked = false;
    for (var i=0;i <currentFGLayers.length;i++) {
      if (key == currentFGLayers[i]) {
	checked = true;
	break;      
      }
    }
    var ob = document.getElementById(id);
    if (ob)
      ob.checked = checked;	
  }
}

function updateMapType(bg_layer, fg_layers) {
  // Set the map type based on the selected background layer and possible fg_layers :
  var zoomStart = 0;
  var zoomEnd = 30;

  
  var tileLayers = new Array();

  // Setup the Background Layer :
  tileLayers[0] = bgDefs[bg_layer][1];

  if (tileLayers[0])
    currentBGLayer = bg_layer;
  else
    tileLayers[0] = bgDefs[currentBGLayer][1];  // XXX Report Error

  if (tileLayers[0].minResolution() > zoomStart) zoomStart = tileLayers[0].minResolution();
  if (tileLayers[0].maxResolution() < zoomEnd)   zoomEnd   = tileLayers[0].maxResolution();

  // Setup the Foreground Layers :
  var newLayers = new Array();
  for (i=0;i<fg_layers.length;i++) {
    var layer = fgDefs[fg_layers[i]][1];
    if (layer) { // XXX Report error
      tileLayers[tileLayers.length] = layer;
      newLayers[newLayers.length] = fg_layers[i];

      if (layer.minResolution() > zoomStart) zoomStart = layer.minResolution();
      if (layer.maxResolution() < zoomEnd)   zoomEnd   = layer.maxResolution();
    }
  }
  currentFGLayers = newLayers; 
   
  var mt = new GMapType(tileLayers, G_SATELLITE_MAP.getProjection(), 'custom',{errorMessage:_mMapError, maxResolution:zoomEnd, minResolution:zoomStart});      
  //map.addMapType(mt); // XXX Required?
  map.setMapType(mt);
}

var filterLayers = new Array();
function writeLayerSelector() {
  // Do *gasp* document.write's to build the current selector based upon the definition data.

  document.write("<form id='layerSelectorForm'><table border=1 cellpadding=2 cellspacing=0>\n");
  document.write("<tr><td class='layerSelectorLabel' >Background : <select id='backgroundLayerSelector' name='background_layer' onchange='backgroundLayerChange(\"backgroundLayerSelector\");'>\n");
  for (var key in bgDefs) {
    var skip = false;
    for (var i=0;i< filterLayers.length;i++) {
      f = filterLayers[i];
      if (f == key) {
	skip = true;
	break;
      }
    }
    if (skip)
      continue;

    var d = bgDefs[key];
    document.write("<option value='" + key + "'>" + d[0]+ "</option>\n");
  }
  document.write("</select></td>\n");
  document.write("<td class='layerSelectorLabel'>Overlay/s : </td>\n");
  for (var key in fgDefs) {

    var skip = false;
    for (var i=0;i< filterLayers.length;i++) {
      f = filterLayers[i];
      if (f == key) {
	skip = true;
	break;
      }
    }
    if (skip)
      continue;

    var d = fgDefs[key];
    document.write("<td>" + d[0] + " : <input id='foregroundLayerSelector_" + key + "' type='checkbox' onClick='foregroundLayerChange(\"foregroundLayerSelector_" + key + "\")'/></td>\n");
  }
  document.write('</tr></table></form>');
}

function backgroundLayerChange(id) {
  var ob = document.getElementById(id);
  var s = ob.options[ob.selectedIndex].text;
  currentBGLayer = ob.options[ob.selectedIndex].value;
  updateMapType(currentBGLayer, currentFGLayers);
}

function foregroundLayerChange(id) {
  var ob = document.getElementById(id);
  var layerKey = id.split('_')[1];
  if (ob.checked) {
    currentFGLayers[currentFGLayers.length] = layerKey; // Add it in
  } else { 
    for (var i=0;i < currentFGLayers.length;i++) {
      if (currentFGLayers[i] == layerKey) {
	currentFGLayers.splice(i,1); // Remove one element at this index.
	break;
      }
    }
  }
  updateMapType(currentBGLayer, currentFGLayers);  
}
