/* Copyright 2008 Google.
 * All rights reserved.
 *
 * Description: Wrapper objects for using the Google
                Maps API with Google Earth Enterprise
 * Version: 1.01
 */

var _fusion_map_server = "http://lnmapas.nacion.co.cr/default_map/";
if (typeof _mFusionMapServer != "undefined" && _mFusionMapServer) {
  _fusion_map_server = _mFusionMapServer + '/';
}

GScript(_fusion_map_server + 'query?request=LayerDefs');
GScript(_fusion_map_server + 'query?request=SearchTabs');

var MAX_ZOOM_LEVEL = 18;

function GFusionMap(container, opts) {
  if (typeof opts != "object") {
    opts = {};
  }
  this.map_layers = [];
  InitLatLngProjectionPrototypes();
  this.initializeLayers();
  if (this.fusion_map_type) {
    opts.mapTypes = [ this.fusion_map_type ];
  }
  GMap2.call(this, container, opts);
}

(function() {
  function C() {}
  C.prototype = GMap2.prototype;
  GFusionMap.prototype = new C;
})();

GFusionMap.prototype.initializeLayers = function() {
  
  var vector_start = 0;

  if (!include_google_layers) {
    // If there are no Google layers, use the first layer as the imagery
    // TODO: Make this more flexible to support multiple imagery backgrounds
    //       and imagery as overlays.
    vector_start = 1;

    var fusion_image_layer = new GFusionTileLayer(tile_layer_defs[0]);
    this.fusion_map_type = new GMapType([fusion_image_layer],
                                        new LatLngProjection(MAX_ZOOM_LEVEL),
                                        tile_layer_defs[0].txt);

    this.allowUsageLogging = function() { return false; }
  }

  // Create tile layers for the remaining vector layers
  for (var lyr = vector_start; lyr < tile_layer_defs.length; ++lyr) {
    this.map_layers.push(new GFusionMapLayer(tile_layer_defs[lyr], lyr));
  }
}

GFusionMap.prototype.showInitialFusionLayers = function() {
  for (var lyr = 0; lyr < this.map_layers.length; ++lyr) {
    if (this.map_layers[lyr].initial_state) {
      this.showFusionLayer(lyr);
    }
  }
}

GFusionMap.prototype.getFusionLayerCount = function() {
  return this.map_layers.length;
}

GFusionMap.prototype.isFusionLayerVisible = function(layerId) {
  return this.map_layers[layerId].enabled;
}

GFusionMap.prototype.showFusionLayer = function(layerId) {
  this.addOverlay(this.map_layers[layerId].overlay);
  this.map_layers[layerId].enabled = true;
}

GFusionMap.prototype.hideFusionLayer = function(layerId) {
  this.removeOverlay(this.map_layers[layerId].overlay);
  this.map_layers[layerId].enabled = false;
}

GFusionMap.prototype.getFusionLayerName = function(layerId) {
  return this.map_layers[layerId].txt;
}

GFusionMap.prototype.getFusionLayerIcon = function(layerId) {
  return this.map_layers[layerId].img;
}

/******************************************************************************
 * GFusionMapLayer
 *  Container class to hold the GTileLayerOverlay and status for a Fusion layer
 ******************************************************************************/
function GFusionMapLayer(layer_def, order) {
  var opts = {};
  if (typeof order == "number") {
    opts.zPriority = order;
  }
  this.overlay = new GTileLayerOverlay(new GFusionTileLayer(layer_def), opts);
  this.initial_state = layer_def.initial_state;
  this.enabled = false;
  this.txt = layer_def.txt;
  this.img = layer_def.img;
}

/******************************************************************************
 * Fusion tile layers
 ******************************************************************************/
function GFusionTileLayer(layer_def) {
  this.fetch_func = layer_def.fetch_func;
  this.zoom_range = layer_def.zoom_range;
  this.opacity = layer_def.opacity;
  this.is_png = layer_def.is_png;
}

GFusionTileLayer.prototype = new GTileLayer(new GCopyrightCollection(""),
                                           1, MAX_ZOOM_LEVEL);

GFusionTileLayer.prototype.getTileUrl = function(addr, level) {
    return this.fetch_func(addr, level);
}

GFusionTileLayer.prototype.isPng = function() {
  return this.is_png;
}

GFusionTileLayer.prototype.getOpacity = function() {
  return this.opacity;
}

/******************************************************************************
 * LatLngProjection
 ******************************************************************************/

/**
 * The LatLng projection used by Fusion.
 * We calculate all the constants we need to use at every zoom level up front
 * to make our conversions more efficient.
 */
function LatLngProjection(zoom_level) {
  var me = this;
  me.pixelsPerLonDegree_ = [];
  me.pixelsPerLonRadian_ = [];
  me.pixelOrigo_ = [];
  me.pixelRange_ = [];

  // Our first zoom level is a single tile
  var pixels = 256;
  for (var z = 0; z <= zoom_level; z++) {
    var origin = pixels / 2;
    me.pixelsPerLonDegree_.push(pixels / 360);
    me.pixelsPerLonRadian_.push(pixels / (2 * Math.PI));
    me.pixelOrigo_.push(new GPoint(origin, origin));
    me.pixelRange_.push(pixels);
    pixels *= 2;
  }
}

LatLngProjection.prototype = 0;

// Initialize LatLngProjection after all javascript has been loaded.
function InitLatLngProjectionPrototypes() {
  LatLngProjection.prototype = new GProjection();

  LatLngProjection.prototype.fromLatLngToPixel = function(latLng, zoom) {
    var me = this;
    var o = me.pixelOrigo_[zoom];
    var x = Math.round(o.x + latLng.lng() * me.pixelsPerLonDegree_[zoom]);
    var y = Math.round(o.y + (latLng.lat() - 360) *  me.pixelsPerLonDegree_[zoom]);
    return new GPoint(x, -y);
  }

  LatLngProjection.prototype.fromPixelToLatLng = function(pixel, zoom,
                                                            opt_nowrap) {
    var me = this;
    var o = me.pixelOrigo_[zoom];
    var lng = (pixel.x - o.x) / me.pixelsPerLonDegree_[zoom];
    var lat = ((pixel.y - o.y) / me.pixelsPerLonDegree_[zoom]);
    return new GLatLng(-lat, lng, opt_nowrap);
  }

  LatLngProjection.prototype.tileCheckRange = function(tile, zoom, tilesize) {
    var range = this.pixelRange_[zoom];
    if (tile.y < 0 || tile.y * tilesize >= range) {
      return false;
    }

    // The map repeats itself in the horizontal direction, so tiles are
    // repeated as well.  Compute the "canonical" tile coordinate.
    if (tile.x < 0 || tile.x * tilesize >= range) {
      var tilerange = Math.floor(range / tilesize);
      tile.x = tile.x % tilerange;
      if (tile.x < 0) {
        tile.x += tilerange;
      }
    }

    return true;
  }

  LatLngProjection.prototype.getWrapWidth = function(zoom) {
    return this.pixelRange_[zoom];
  }
}
