// global variables and constants
var map;
var ie55 = false;
var isEnglish = location.href.indexOf('_e') > 0;
var mapCentre = new GLatLng(30.0, -6.0);
var grid = null;
var listeners = new Array();
var markers = new Array();
function addListener(obj, event, f) {
  listeners[event] = GEvent.addListener(obj, event, f);
}
function removeListener(event) {
  GEvent.removeListener(listeners[event]);
  listeners[event] = null;
}
var wpoints = [
  [30.372283,-5.841062,102],
  [30.12925,-6.1071,103],
  [30.0702,-6.08665,104],
  [30.04565,-6.07775,106],
  [30.001317,-6.06645,107],
  [29.866467,-6.182433,111],
  [29.766717,-6.110483,116],
  [30.719852,-6.601733,117],
  [31.626185,-7.987763,124]
];
var colours = new Array(9);

// Projection
var RefProjection = new GMercatorProjection(18);
var GPSProjection = new GProjection();
// virtual map dimensions (pixel) for selected zoom levels
GPSProjection.mapResolutions = new Array();
GPSProjection.mapResolutions[17] = 69120000; // damn polyline
GPSProjection.mapResolutions[13] =  2764800;
GPSProjection.mapResolutions[12] =  1382400;
GPSProjection.mapResolutions[11] =   691200;
GPSProjection.mapResolutions[10] =   276480;
GPSProjection.mapResolutions[9]  =   138240;
// actual dimensions (tiles)
GPSProjection.mapDimensions = new Array();
GPSProjection.mapDimensions[13] = new GPoint(31, 35);
GPSProjection.mapDimensions[12] = new GPoint(16, 18);
GPSProjection.mapDimensions[11] = new GPoint(8, 9);
GPSProjection.mapDimensions[10] = new GPoint(7, 8);
GPSProjection.mapDimensions[9]  = new GPoint(4, 3);
GPSProjection.pixelOrigin = function(zoom) {
  var origX = Math.floor((this.mapResolutions[zoom] / 360) * (zoom > 10 ? 173.5 : 173));
  var origY = Math.floor(RefProjection.fromLatLngToPixel(new GLatLng(zoom > 10 ? 30.5 : 31, 0), zoom).y *
    (this.mapResolutions[zoom] / RefProjection.getWrapWidth(zoom)));
  return new GPoint(origX, origY);
}
GPSProjection.normalizedPixel = function(pixel, zoom) {
  var origin = this.pixelOrigin(zoom);
  var normX = (pixel.x - origin.x + this.mapResolutions[zoom]) % this.mapResolutions[zoom];
  var normY = pixel.y - origin.y;
  return new GPoint(normX, normY);
}
GPSProjection.universalPixel = function(pixel, zoom) {
  var origin = this.pixelOrigin(zoom);
  var univX = (pixel.x + origin.x) % this.mapResolutions[zoom];
  var univY = pixel.y + origin.y;
  return new GPoint(univX, univY);
}
GPSProjection.fromLatLngToPixel = function(latlng, zoom) {
  var x = Math.floor((this.mapResolutions[zoom] / 360) * (latlng.lng() + 180));
  var y = Math.floor(RefProjection.fromLatLngToPixel(latlng, zoom).y *
    (this.mapResolutions[zoom] / RefProjection.getWrapWidth(zoom)));
  return this.normalizedPixel(new GPoint(x, y), zoom);
}
GPSProjection.fromPixelToLatLng = function(pixel, zoom, unbounded) {
  var univPixel = this.universalPixel(pixel, zoom);
  var lat = RefProjection.fromPixelToLatLng(new GPoint(0, Math.floor(univPixel.y * RefProjection.getWrapWidth(zoom) / this.mapResolutions[zoom])), zoom, false).lat();
  var lng = univPixel.x * 360 / this.mapResolutions[zoom] - 180;
  return new GLatLng(lat, lng);
}
GPSProjection.tileCheckRange = function(tile, zoom, tileSize) {
  var rez = this.mapResolutions[zoom];
  var e = Math.floor(rez / tileSize);
  if (tile.x < 0 || tile.x * tileSize >= rez) {
    tile.x = tile.x % e;
    if (tile.x < 0) { tile.x += e; }
  }
  return true;
}
GPSProjection.getWrapWidth = function(zoom) {
  return this.mapResolutions[zoom];
}

// Tile Layer
var copy = new GCopyrightCollection(isEnglish ? "Map data:" : "Kartendaten:");
copy.addCopyright(new GCopyright('moroccomaps', new GLatLngBounds(new GLatLng(-90, -180), new GLatLng(90, 180)),
  0, '&copy; <a href="http://www.island-olaf.de/travel/marokko/index-' + (isEnglish ? 'en' : 'de') + '.html" target="_blank">Olaf K&auml;hler</a>'));
var tiles = new GTileLayer(copy, 9, 13);
tiles.getTileUrl = function(tile, zoom) {
  if (zoom > this.maxResolution() || zoom < this.minResolution() || tile.x < 0 || tile.y < 0 ||
      tile.x >= GPSProjection.mapDimensions[zoom].x || tile.y >= GPSProjection.mapDimensions[zoom].y) {
    return 'tiles/nil.png';
  }
  return 'tiles/t' + (zoom - 1) + '.' + (tile.x + GPSProjection.mapDimensions[zoom].x * tile.y) + '.png';
}
tiles.isPng = function() { return true; }
tiles.getOpacity = function() { return 1.0; }

// Map Type
GMapType.prototype.getMinimumResolution = function(latlng) {
  return 9;
}
GMapType.prototype.getMaximumResolution = function(latlng) {
  return 13;
}
G_HYBRID_MAP.gridColor = '#CCC';
var GPSMap = new GMapType(
  [tiles],
  GPSProjection,
  'MapEdit',
  {
    shortName: 'GPS',
    tileSize: 256,
    linkColor:'#000'
  }
);
GPSMap.gridColor = '#808080';

// Grid Overlay
function GridOverlay() {
}
GridOverlay.prototype = new GOverlay();
GridOverlay.prototype.gridSteps = [5400, 3600, 1800, 1200, 600, 300, 120, 60, 30, 20, 10, 5, 2, 1, 1, 1, 1, 1];
GridOverlay.prototype.initialize = function(map) {
  var div = document.createElement("div");
  div.style.position = "absolute";
  div.style.fontFamily = "Tahoma,Arial,Helvetica,sans-serif";
  div.style.fontSize = "xx-small";
  div.style.overflow = "hidden";
  div.style.visibility = "hidden";

  map.getPane(G_MAP_MAP_PANE).appendChild(div);
  addListener(map, "movestart", function() {
    div.style.visibility = "hidden";
  });
  var self = this;
  addListener(map, "moveend", function() {
    self.redraw(true);
  });
  addListener(map, "resize", function() {
    self.redraw(true);
  });

  this.map_ = map;
  this.div_ = div;

  return div;
}
GridOverlay.prototype.remove = function() {
  this.div_.parentNode.removeChild(this.div_);
  removeListener("movestart");
  removeListener("moveend");
  removeListener("resize");
}
GridOverlay.prototype.copy = function() {
  return new GridOverlay();
}
function format(deg) {
  var pos = Math.abs(deg) + 0.0000005;
  var min = Math.floor(pos * 60) % 60;
  return '<div style="position:absolute; top:2px; left:2px;">' + Math.floor(pos) + '&deg;&nbsp;' + (min < 10 ? '0' : '') + min + "'</div>";
}
GridOverlay.prototype.redraw = function(force) {
  if (!force) { return; }

  while (this.div_.hasChildNodes()) { this.div_.removeChild(this.div_.firstChild); }
  var bounds = this.map_.getBounds();
  var sw = this.map_.fromLatLngToDivPixel(bounds.getSouthWest());
  var ne = this.map_.fromLatLngToDivPixel(bounds.getNorthEast());
  this.div_.style.color = this.map_.getCurrentMapType().gridColor;
  this.div_.style.top = ne.y + "px";
  this.div_.style.left = sw.x + "px";
  this.div_.style.width = this.map_.getSize().width + "px";
  this.div_.style.height = this.map_.getSize().height + "px";
  
  var step = this.gridSteps[this.map_.getZoom()] / 60;
  var w = Math.ceil(bounds.getSouthWest().lng() / step) * step;
  var s = Math.ceil(bounds.getSouthWest().lat() / step) * step;
  for (var next = w; next <= bounds.getNorthEast().lng() + 0.00005; next += step) {
    var div = document.createElement("div");
    div.style.position = "absolute";
    div.style.top = "0px";
    div.style.left = (this.map_.fromLatLngToDivPixel(new GLatLng(s, next)).x - sw.x) + "px";
    div.innerHTML = '<img src="pixel.png" width="1" height="' + this.map_.getSize().height + '" />' + format(next);
    this.div_.appendChild(div);
  }
  for (var next = s; next <= bounds.getNorthEast().lat() + 0.00005; next += step) {
    var div = document.createElement("div");
    div.style.position = "absolute";
    div.style.top = (this.map_.fromLatLngToDivPixel(new GLatLng(next, w)).y - ne.y) + "px";
    div.style.left = "0px";
    div.innerHTML = '<img src="pixel.png" width="' + this.map_.getSize().width + '" height="1" align="top" />' + format(next);
    this.div_.appendChild(div);
  }
  this.div_.style.visibility = "visible";
}

// OnOffControl
function OnOffControl(onImage, offImage, pos, onTrue, onFalse, initState, title) {
  this.on_ = onImage;
  this.off_ = offImage;
  this.pos_ = pos;
  this.onTrue_ = onTrue || function() { };
  this.onFalse_ = onFalse || function() { };
  this.st_ = initState;
  this.tit_ = title || "";
  this.grp_ = null;
}
OnOffControl.prototype = new GControl();
OnOffControl.prototype.initialize = function(map) {
  var container = document.createElement("div");
  container.style.cursor = ie55 ? "hand" : "pointer";
  container.style.width = '34px';
  container.style.height = '22px';
  container.title = this.tit_;
  container.innerHTML = '<div style="position:absolute; top:2px; left:2px; width:32px; height:20px;"><img src="shadow.png" /></div>' +
    '<div style="position:absolute; top:0px; left:0px; width:30px; height:18px; border:solid 1px #000; background-color:#fff;"><img id="' + this.on_ +
    '" src="' + (this.st_ ? this.on_ : this.off_) + '" /></div>';
  var self = this;
  GEvent.addDomListener(container, "click", function() {
    if (!self.grp_ || !self.st_) { self.changeState(); }
  });
  map.getContainer().appendChild(container);
  return container;
}
OnOffControl.prototype.getDefaultPosition = function() {
  return this.pos_;
}
OnOffControl.prototype.changeState = function() {
  if (!this.st_ && this.grp_) {
    this.grp_.getSelected().changeState();
    this.grp_.setSelected(this);
  }
  this.st_ = !this.st_;
  document.getElementById(this.on_).src = (this.st_ ? this.on_ : this.off_);
  this.st_ ? this.onTrue_() : this.onFalse_();
}
OnOffControl.prototype.getState = function() {
  return this.st_;
}
OnOffControl.prototype.addToGroup = function(grp) {
  this.grp_ = grp;
}

// OnOffGroup
function OnOffGroup() {
  this.sel_ = null;
}
OnOffGroup.prototype.addOption = function(ctrl) {
  ctrl.addToGroup(this);
  if (ctrl.getState()) { this.sel_ = ctrl; }
}
OnOffGroup.prototype.getSelected = function() {
  return this.sel_;
}
OnOffGroup.prototype.setSelected = function(ctrl) {
  this.sel_ = ctrl;
}

var icon = new GIcon();
icon.shadow = "pin_shadow.png";
icon.iconSize = new GSize(32, 32);
icon.shadowSize = new GSize(59, 32);
icon.iconAnchor = new GPoint(9, 31);
function randomise() {
  for (var i = 0; i < 9; i++) { colours[i] = i; }
  for (var i = 0; i < 8; i++) {
    var r = Math.floor(Math.random() * (9 - i));
    if (r > 0) {
      var t = colours[i];
      colours[i] = colours[i + r];
      colours[i + r] = t;
    }
  }
}
function addMarkers() {
  randomise();
  for (var i in wpoints) {
    var marker = createMarker(wpoints[i], colours[i]);
    map.addOverlay(marker);
    markers.push(marker);
  }
}
function createMarker(p, c) {
  var marker = new GMarker(new GLatLng(p[0], p[1]), {
    icon: new GIcon(icon, "pin" + c + ".png"),
    clickable: true
  });
  GEvent.addListener(marker, "click", function() {
    var div = document.createElement("div");
    var w = map.getSize().width;
    var imw = Math.min(1200, w - 20);
    div.style.position = "absolute";
    div.style.top = map.getContainer().style.top;
    div.style.left = map.getContainer().style.left;
    div.style.width = w + 'px';
    div.style.height = map.getSize().height + 'px';
    div.style.backgroundImage = "url(trans.png)";
    div.style.cursor = ie55 ? "hand" : "pointer";
    div.title = (isEnglish ? "Click to close" : "zur Karte");
    div.innerHTML = "<img src='ma" + p[2] + ".jpg' style='width:" + imw + "px;position:absolute;left:" + Math.floor((w - imw)/2) + "px;top:20%' />";
    GEvent.addDomListener(div, "click", function() {
      div.parentNode.removeChild(div);
    });
    document.getElementsByTagName("body")[0].appendChild(div);
  });
  return marker;
}

// map setup
function load() {
  if (GBrowserIsCompatible()) {
    // create new Map object
    map = new GMap2(document.getElementById("map"), {mapTypes:[GPSMap, G_HYBRID_MAP], logoPassive:true});
    map.enableDoubleClickZoom();
    map.enableContinuousZoom();
    // position the map
    map.setCenter(mapCentre, 10, GPSMap);
    if (!ie55) {
      // add polyline in all browsers but IE 6-
      var points = "ox`wDlwld@~oAoo@tsAqmBjvCasDtxEfs@lxCsv@btGseAxfD`z@nyAzaAhnCjbDpfCpmDrpH`dGlhAz|EnDbfA|~@js@`}Awz@daAat@lf@y|GbjAgvBri@ifDbbD{lBjoFwfCvnCmeDxxBqkGoJcuBmbCc`Efh@}kCw}BepDy_BaqFxOicGauBy~CasDotBabCwlCylBg{H";
      var levels = "BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
      var route = new GPolyline.fromEncoded({
        color: "#0000ff",
        weight: 5,
        points: points,
        levels: levels,
        zoomFactor: 32,
        numLevels: 4
      });
      map.addOverlay(route);
    }
    grid = new GridOverlay();
    map.addOverlay(grid);
    addMarkers();
    map.addControl(new GLargeMapControl());
    map.addControl(new GScaleControl());
    var mapTypes = new OnOffGroup();
    var jctrl = new OnOffControl("jon.png", "joff.png", new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 7)),
      function() { map.setMapType(GPSMap); }, null,
      true, (isEnglish ? 'Show GPS map' : 'GPS-Karte anzeigen'));
    mapTypes.addOption(jctrl);
    map.addControl(jctrl);
    var gctrl = new OnOffControl("goon.png", "gooff.png", new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 32)),
      function() { map.setMapType(G_HYBRID_MAP); }, null,
      false, (isEnglish ? 'Show satellite images' : 'Satellitenbilder anzeigen'));
    mapTypes.addOption(gctrl);
    map.addControl(gctrl);
    map.addControl(new OnOffControl("gridon.png", "gridoff.png", new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 57)),
      function() { grid = new GridOverlay(); map.addOverlay(grid); }, function() { map.removeOverlay(grid); grid = null; },
      true, (isEnglish ? 'Grid on/off' : 'Raster ein/aus')));
    map.addControl(new OnOffControl("markon.png", "markoff.png", new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7, 82)),
      addMarkers, function() { while (markers.length) map.removeOverlay(markers.pop()); },
      true, (isEnglish ? 'Markers on/off' : 'Marker ein/aus')));
  } else {
    var warntext = isEnglish ?
      "Unfortunately, your browser isn't supported by Google Maps. A list of <a href='http://maps.google.com/support/bin/answer.py?answer=16532&amp;topic=1499'>compatible browser versions</a> is available from a Google site." :
      "Leider wird Ihr Browser von Google Maps nicht unterst&uuml;tzt. Eine <a href='http://maps.google.com/support/bin/answer.py?answer=16532&amp;topic=1499'>Liste unterst&uuml;tzter Browserversionen</a> ist direkt bei Google einsehbar.";
    document.getElementById("map").innerHTML = warnText;
  }
}
