
// for debugging use firefox and firebug plugin/addon
// set in about:config -> javascript.options.strict = true
// you can use console.log("bla") for debug output, but should first ask whether object exists


// config, init, draw tiles on map
var mapBaseUrl = './tiles/'; // todo// 'file:///home/marc/mmweb/micromap-web/a1map/tiles/'; // todo
var mapWidth = 600;
var mapHeight = 400;   
var zoomLevel = 15;
var zoomMax = 16;
var zoomMin = 13;
var tileWidth = 256;
var tileHeight = 256;
var tilesX = parseInt(mapWidth  / tileWidth )+2;
var tilesY = parseInt(mapHeight / tileHeight)+2;
var baseTileX = 0; // reference tile, use modulo
var baseTileY = 0;

var maxTileX = 0;
var maxTileY = 0;

//performance improvement: instead of asking dom which tile has to be redrawn use a 2dim tile array!!.. 
var tileLastImg = new Array();

var oldBaseTileX = baseTileX; // needed for rearrangement of div tiles
var oldBaseTileY = baseTileY;

var divTileX = 0;
var divTileY = 0;
var divTilePosX = 0;
var divTilePosY = 0;

var baseX = 0; //debug
var baseY = 0; //debug
var isMapOutdated = true;

var threadId = 0;
var lastThreadId = 0;
var debug = false;
//if (!console)  {  alert("hase"); debug=false;}
//if (!console) debug = false;

// todo: maxTiles ausrechnen!
function updateZoom(newZoom) {
  var relX=null, relY=null;
  var oldZoom = zoomLevel;
  var diffZoom = 0;
  if (newZoom > zoomMax) newZoom = zoomMax;
  if (newZoom < zoomMin) newZoom = zoomMin;

  if (newZoom != oldZoom) {
    // calc current rel mapCenter
    var mapCenterX = document.getElementById('map').offsetLeft - mapWidth /2;
    var mapCenterY = document.getElementById('map').offsetTop  - mapHeight/2;
    // zoomIn key "+"
    if(oldZoom > newZoom) {
      diffZoom = oldZoom - newZoom;
      mapCenterX = (mapCenterX * Math.pow(2, diffZoom)) + mapWidth/2;
      mapCenterY = (mapCenterY * Math.pow(2, diffZoom)) + mapHeight/2;
    }
    // zoomOut key "-"
    if(oldZoom < newZoom) { 
      diffZoom = newZoom - oldZoom;
      mapCenterX = (mapCenterX / Math.pow(2, diffZoom)) + mapWidth/2;
      mapCenterY = (mapCenterY / Math.pow(2, diffZoom)) + mapHeight/2;
    }
    baseTileX = -parseInt(mapCenterX / tileWidth);
    baseTileY = -parseInt(mapCenterY / tileHeight);
    relX = parseInt(mapCenterX + (baseTileX * tileWidth));
    relY = parseInt(mapCenterY + (baseTileY * tileHeight));
    zoomLevel = newZoom;
    initTiles(); // kill old bg img and old bg img marker array
    moveRelMapToBaseTile(relX, relY);
  }
}

function initMap() {
  // set the config for the map
  document.getElementById('map').style.width        = mapWidth  +'px';
  document.getElementById('map').style.height       = mapHeight +'px';
  document.getElementById('viewport').style.width   = mapWidth  +'px';
  document.getElementById('viewport').style.height  = mapHeight +'px';
  document.getElementById('clickport').style.width  = mapWidth  +'px';
  document.getElementById('clickport').style.height = mapHeight +'px';
  initTiles();
  centerMap();
  //moveMapToBaseTile();
  document.onkeypress = showPress;
  Drag.init(document.getElementById("map"), null); //, 0,0,-50000, +50000); //, 0, 0); //, -mapWidth, +mapWidth); //, -mapHeight, +mapHeight);
}
	

// *** wrapper ***
function moveMapToBaseTile() {
  moveRelMapToBaseTile(null, null);
}

// *** moves relMap to left upper basetileX/Y and respects also relative user offset (should be maybe /2 or *2 with respect to zoom?) ***
function moveRelMapToBaseTile(relX, relY) {
  var obj = document.getElementById("map");
  if (relX == null) relX = obj.offsetLeft % tileWidth;
  if (relY == null) relY = obj.offsetTop % tileHeight;
  obj.style.left = -(baseTileX * tileWidth)  + relX + 'px';
  obj.style.top  = -(baseTileY * tileHeight) + relY + 'px';
  updateAllTiles();
}

function moveMapRelative(x,y) {
  var obj = document.getElementById("map");
  obj.style.left = obj.offsetLeft + x +'px';
  obj.style.top  = obj.offsetTop  + y +'px';
}

function centerMap() {
  var startX = (((maxTileX+1) * tileWidth)  / 2) - (mapWidth  / 2);
  var startY = (((maxTileY+1) * tileHeight) / 2) - (mapHeight / 2);
  baseTileX = parseInt(startX / tileWidth);
  baseTileY = parseInt(startY / tileHeight);
  var relX = -parseInt(startX - (baseTileX * tileWidth));
  var relY = -parseInt(startY - (baseTileY * tileHeight));
  moveMapToBaseTile();
  moveMapRelative(relX, relY);
}

// *** init fillup map with tile div elements (no bgimages & no positions, use updateTiles for that ***
function initTiles() {
  var x=0, y=0;
  var strTiles = '';
  initTileLastImgArray();
  for(y = 0; y < tilesY; y++) {
    for(x = 0; x < tilesX; x++) {
      //strTiles += '<div class="map_tile" id="tile_'+ ((baseTileX + x) % tilesX) +'_' + ((baseTileY + y) % tilesY) + '" style="left:-1024px;top:-1024px;"></div>';
      strTiles += '<div class="map_tile" id="tile_'+x +'_' +y + '" style="left:-1024px;top:-1024px;"></div>';
    }
  }
  //document.getElementById('map').innerHTML.replace(/.*/g, '');
  document.getElementById('map').innerHTML = strTiles;
  //alert(document.getElementById("map").innerHTML);
  updateAllTiles();
}

// *** inits marker 1dim-array for which tiles has which bg img
function initTileLastImgArray() {
  var x=0, y=0;
  for(y = 0; y < tilesY; y++) {
    for(x = 0; x < tilesX; x++) {
      tileLastImg[(y * tilesX) + x] = 0;
    }
  }
}


// *** update tile bgimages and positions ***
// tileX/Y is first left up tile and same as baseTileX/Y 
// (caution: could be changed "under the seat" during function, so better overgiven as parameter)
// old nasty way: from xBegin to xEnd and yBegin to yEnd
function updateTiles(tileX, tileY) { // old: , xBegin, yBegin, xEnd, yEnd) {
  var x=0, y=0, resX=0, resY=0, realX=0, realY=0;
  var tileId = '', tileImg = '', tileUrl = '', tileObj = null;
  var tileLastUsedImg = null;
  maxTileX = maxTileY = Math.pow(2, 17-zoomLevel)-1; // should be only called if zoom changed?

  // run for all tiles from 0..tilesX/Y -1, where tilesX/Y is count of tiles needed for viewport room + reserve tiles at the borders
  for(y = 0; y < tilesY; y++) {
    for(x = 0; x < tilesX; x++) {
      resX = tileX + x;
      resY = tileY + y;
      if ( (resX >= 0 && resX <= maxTileX) && (resY >= 0 && resY <= maxTileY) ) {
        tileImg = zoomLevel + '/T-' + resX + '-' + resY + '.gif';
        if (tileLastImg[(y * tilesX) + x] != tileImg) {
          tileObj = document.getElementById( 'tile_' + (resX % tilesX)  + '_' + (resY % tilesY) );
          tileObj.style.backgroundImage = 'url(' + mapBaseUrl + tileImg + ')';
          tileObj.style.left = ( resX * tileWidth  ) +'px';
          tileObj.style.top  = ( resY * tileHeight ) +'px';
          tileLastImg[(y * tilesX) + x] = tileImg;
        }
      }
    }
  }
}

// *** wrapper function to update ALL tiles ***
function updateAllTiles() {
  updateTiles(baseTileX, baseTileY); // old: , 0, 0, tilesX-1, tilesY-1);
}
// *** wrapper function for document.getElementById(obj) - use it only for non-performance ops? ***
function $(obj) {
  return document.getElementById(obj);
}


function showPress(event) {
  //alert(event);
  switch (event.keyCode) {
    case 37: // cursor left
      if (baseTileX > 0) baseTileX = baseTileX-1; 
      moveRelMapToBaseTile(0,0);
      break;
    case 38: // cursor up
      if (baseTileY > 0) baseTileY = baseTileY-1; 
      moveRelMapToBaseTile(0,0);
      break;
    case 39: // cursor right
      if (baseTileX <= maxTileX-tilesX+ ((mapWidth  % 256 == 0) ? 2:1) ) baseTileX = baseTileX+1; 
      moveRelMapToBaseTile(0,0);
      break;
    case 40: // cursor down
      if (baseTileY <= maxTileY-tilesY+ ((mapHeight % 256 == 0) ? 2:1) ) baseTileY = baseTileY+1; 
      moveRelMapToBaseTile(0,0);    
      break;
  }
  switch ( (event.charCode ? event.charCode : event.which) ) { // workaround for opera which doesnt know charCode
    case 43: // plus key
      updateZoom(zoomLevel-1); // zoomLevel=16 is world in 2x2, 15 is world in 4x4, ...
      break;
    case 45: // minus key
      updateZoom(zoomLevel+1);
      break;
  }
  return false; // preventing from further firing and e.g. scrolling the page
}

//alert(parseInt (+256/256) );

var realViewportOffsetX = document.getElementById('viewport').offsetLeft;
var realViewportOffsetY = document.getElementById('viewport').offsetTop;
var mousePosInMapX = -1;
var mousePosInMapY = -1; 

var isDragging = false;
var oldMouseX = 0;
var oldMouseY = 0;

function setDrag(state) {
    isDragging = state;
}

function getMousePos(event) {
  mousePosInMapX = event.clientX - realViewportOffsetX;
  mousePosInMapY = event.clientY - realViewportOffsetY;
}

function mapMouseOver(event) {
  getMousePos(event);
  var mapRelPosX = document.getElementById('map').offsetLeft;
  var mapRelPosY = document.getElementById('map').offsetTop;
    
  oldBaseTileX = baseTileX;
  oldBaseTileY = baseTileY;
  baseTileX = -parseInt(mapRelPosX / 256);
  baseTileY = -parseInt(mapRelPosY / 256);
  
  
  if (baseTileX != oldBaseTileX || baseTileY != oldBaseTileY) {
    //if ( (baseTileX >= 0 && baseTileX+tilesX-1 <= maxTileX) && (baseTileY >= 0 && baseTileY+tilesY-1 <= maxTileY) ) 
    {
      updateAllTiles();
    }
  }

var latitude = 0;
var longitude = 0;
var width  = 2048; //maxTileX * tileWidth;
var height = 2048; //maxTileY * tileHeight;
//alert(height);


var radius = height / (2 * Math.PI);

longitude = -((((width  - (-mapRelPosX + event.clientX - realViewportOffsetX)) / width ) * 360) - 180); // Breitengrad
latitude  = (-mapRelPosY + event.clientY - realViewportOffsetY) -(height/2); // ((((height - (-mapRelPosY + event.clientY - realViewportOffsetY)) / height) * 360) - 180); // * 180) - 90);

// ggl uses mercator projection!
latitude =  (Math.PI/2) - (2 * Math.atan(Math.exp(-1.0 * latitude / radius)));
latitude = -(latitude*180/Math.PI); // radiansToDegrees(latitude); -> latitude*180/Math.PI = latitude * 57.29578


//((mapRelPosY -  event.clientY + realViewportOffsetY) / width * 360); //((((height  - (-mapRelPosY + event.clientY - realViewportOffsetY)) / height ) * 180) -90 ); // Laengengrad
//180 * ((((-mapRelPosY + event.clientY - realViewportOffsetY) / width)) -0.5 ); //*360) -180; // ((((height - (-mapRelPosY + event.clientY)) / height) * 180) -  90);



  document.getElementById('debugOutput').innerHTML = 
    "mousePosInMap: " + mousePosInMapX + "/" + mousePosInMapY + "<br>"
    + "geoPos: " + longitude + "/" + latitude + "<br>"
    + "relPosOfMap: " + mapRelPosX + "/" + mapRelPosY + "<br>"
    + "baseTile: " + baseTileX + "/" + baseTileY + "<br>"
    + "zoomLevel: " + zoomLevel + "<br>"
    + "threads: "+threadId+ " "+lastThreadId +"<br>"
    + "Drag: "+isDragging;



//     var leftPixel = event.clientX + 10; 
} 




