///////////////////////////////////////////////////////////////////////////
//                                                                       //
//  Name:   maps.js                                                   //
//  Autor:  Philipp Schäufele                                            //
//  Email:  philipp.schaeufele[at]gmx.de                                 //
//                                                                       //
//  Funktionen zur Anzeige von Karten und Kartenpunkten                  //
//                                                                       //
//  Diese Funktionen sind urheberrechtlich geschützt! Verwendung (auch   //
//  partiell) nicht ohne meine schriftliche Genehmigung. Auch in         //
//  kommerziellem Umfeld wird sich die "Entlohnung" normalerweise durch  //
//  eine Namensnennung und einen Link erledigt haben!                    //
//                                                                       //
///////////////////////////////////////////////////////////////////////////

// Konstanten
var FadeInterval    = 100;  // ms
var EnlargeSteps    = 10;
var EnlargeInterval = 25;   // ms

// default-Größe der Karte
var defaultMapX = 200;
var defaultMapY = 270;

var boxBorderWidth = 2;     // Breite des Rands der Mapbox
var boxBorderColor = "red";  

var symbolsDir = "./Symbols/"   // Pfad zum Verzeichnis mit den Symbolen
var Image1px = "1px.png";       // Pfad+Dateiname zum Bild, das einen durchsichtigen Pixel enthält

// globale Variablen
var mainMapDiv;
var mainMapImg;
var currentMap;

// ID des Timers, der das blinken eines MapItmes steuert, wir benötigt, um das beim Kartenwechsel abzubrechen
var blinkTimeoutID = [0, 0];

var loaded = false;

// "Zeiger" auf die Datenstrukturen des jeweiligen Hauptfensters
var maps;
var places;

// allgemein, was kann ich von extern aufrufen?
// changeMap ("Kartenname", Infostrukturen)
//  - Karte zu "Kartenname" ändern
// setPlace  ("Ortsname")
//  - lässt den "Ortsname" blinken

// ToDo:
// - Click auf den Ort lässt Liste von Einträgen erscheinen
// - Kein blinkender Punkt sondern größenveränderlicher Punkt wie bei http://www.travelpod.com/travel-blog-entries/jkirby/world2007/1197640920/tpod.html#ENTRY_LIST z.B.


              
/****************************************************
 * Diese Funktion wird aufgerufen, sobald die Seite *
 * geladen wurde                                    *
 ****************************************************/
function pageLoaded_Maps()
{
  mainMapDiv = document.getElementById("mapDiv");
  mainMapImg = document.getElementById("mapImg");

  loaded = true;

  // wenn das Hauptfenster keine Karte vorgegeben hat die Weltkarte laden
  if (typeof currentMap == 'undefined')
    currentMap = maps[0];
  
  displayMap(); 

 
  // BUGME
return;

  InitDebug();


  var i;
  for (i=0; i<maps[0].childMaps.length; i++)
    drawMapBox(maps[0].childMaps[i]);
  for (i=0; i<maps[0].places.length; i++)
    drawMapPoint(0, maps[0].places[i]);
    
  window.setTimeout (function(){mapItemBlink("Bangkok",100);},100)
      
}

/****************************************************
 * eine andere Karte anzeigen                       *
 * Parameter: Name/Nummer der Karte                 *
 *            Datenstrukturen mit Karten/Ortsinfo   *
 ****************************************************/
// BUGME: abfragen, ob das Kartenbild da ist
function changeMapInt(mapName, mapInfo, placeInfo)
{   
  if (mapName == "")
    return;

  // alte mapItems entfernen 
  var i;

  if ((typeof currentMap != 'undefined') && (typeof places != 'undefined'))
  {
    if (typeof currentMap.places != 'undefined')
    {
      for (i=0; i<currentMap.places.length; i++)
      {
        place = searchPlace(currentMap.places[i]);
        mainMapDiv.removeChild(document.getElementById("mapPointDiv"+place));
      }
    }
  }
  
  if (blinkTimeoutID[0] != 0)  
  {
    clearTimeout(blinkTimeoutID[0]);
    blinkTimeoutID[0] = 0;
  }
  if (blinkTimeoutID[1] != 0)  
  {
    clearTimeout(blinkTimeoutID[1]);
    blinkTimeoutID[1] = 0;
  }
  
  // neue Karten/Ort-Informationsstrukturen merken
  maps = mapInfo; places = placeInfo
  // Karte suchen
  var mapNumber = searchMap(mapName);
  // Karte gefunden?
  if (mapNumber == -1)
  {
    alert ("Karte " + mapName + " nicht gefunden!");
    return;
  }
  currentMap = maps[mapNumber];

  // wenn das Hauptframe versucht die Karte zu ändern bevor das Kartenframe geladen wurde
  // Karte erst später laden
  if (!loaded) 
    return;
  
  displayMap(); 
  
}


function displayMap()
{
  var i;

  // Größe des Frames anpassen
  // BUGME: + 30 ist einfach nur geschätzt...
  var height = currentMap.height + 30;
  parent.document.getElementById('leftSide').setAttribute('rows', height+',*', 0); 
  
  mainMapImg.src   = currentMap.src;
  mainMapImg.title = currentMap.name;
  
  for (i=0; i<currentMap.places.length; i++)
    drawMapPoint(currentMap.places[i]);
  
  /*
  var a = document.createElement("a");  
  var text = document.createTextNode("Testblablub");
  a.appendChild(text);
  mainMapDiv.appendChild(a); */
}


/****************************************************
 * Lässt den angegebenen Kartenpunkt blinken        *
 ****************************************************/
 // setPlace befindet sich in tools.js
 // BUGME: nicht nur ein Name sollte möglich sein, auch direkte Koordinaten ergänzenderweise
 //        dieser Punkt wird dann nur in den entsprechenden Reiseberichten gezeigt
 //        v.a. Seetage auf AIDA-Reisen!
function setPlaceInt(name)
{
  if (name == "")
    return;

  // BUGME: nicht nur places
  if (searchPlace(name) == -1)
    return;  
  
  if (blinkTimeoutID[0] == 0)
    blinkTimeoutID[0] = window.setTimeout (function(){mapItemBlink(name,100,0);},100);
  else if (blinkTimeoutID[1] == 0)
    blinkTimeoutID[1] = window.setTimeout (function(){mapItemBlink(name,100,1);},100);
  else
    debugAlert ("Zu viele Blink-Items!");
}


function searchMap(mapName)
{
  if (typeof mapName == 'number')
    return mapName;
    
  for (i=0; i<maps.length; i++)
  {
    if (maps[i].name == mapName)
      return i;
  }
  
  return -1;
}

function searchPlace(placeName)
{
  if (placeName == "")
    return -1;

  if (typeof placeName == 'number')
    return placeName;
    
  for (i=0; i<places.length; i++)
  {
    if (places[i].name == placeName)
      return i;
  }
  // DebugOut ("searchPlace: Place " + placeName + " not found!\n");
  
  return -1;
}


/****************************************************
 * Fügt eine Karten-Box hinzu                       *
 * Argumente: Name oder Nummer der Karte            *
 ****************************************************/
// BUGME: preloaden des entsprechenden Kartenbildes
function drawMapBox(mapName)
{
  var mapNumber = searchMap(mapName);
  if (typeof mapNumber == 'undefined')
  {
    // DebugOut ("drawMapBox: Map " + mapName + " not found!\n");
    return false;
  }
    
  // Haupt-Kartengrenzen
  var map = new Object();
  getMapCoords(map, maps[0]);         //BUGME

  // Box-Kartengrenzen
  var box = new Object();
  getMapCoords(box, maps[mapNumber]);
  
  // Koordinatenberechnung
  // BUGME: auf in der Kartenstruktur angegebene Höhe beziehen!
  var left   = (box.left-map.left)     * defaultMapX / (map.right-map.left) - boxBorderWidth;
  var right  = (box.right-map.left)    * defaultMapX / (map.right-map.left) - boxBorderWidth;
  var top    = (box.top-map.top)       * defaultMapY / (map.bottom-map.top) - boxBorderWidth;
  var bottom = (box.bottom-map.top)    * defaultMapY / (map.bottom-map.top) - boxBorderWidth;

  var mapBoxImg = new Image();
  var mapBoxDiv = document.createElement("div")
  mapBoxDiv.id      = "mapDivNew" + mapNumber;
  mapBoxDiv.onclick = function() {enlargeMap(mapNumber);};
  mapBoxDiv.style.position    = "absolute";
  mapBoxDiv.style.top         = top  + "px";
  mapBoxDiv.style.left        = left + "px";
  mapBoxDiv.style.borderColor = boxBorderColor;
  mapBoxDiv.style.borderWidth = boxBorderWidth + "px";
  mapBoxDiv.style.borderStyle = "solid";
  mapBoxDiv.style.cursor      = "pointer";
  mapBoxImg.src   = Image1px;
  mapBoxImg.id    = "mapImageNew" + mapNumber;
  mapBoxImg.width = right-left;
  mapBoxImg.height= bottom-top;
  mapBoxImg.title = maps[mapNumber].name;  
  setOpacity (mapBoxDiv,40);
    
  mapBoxDiv.appendChild(mapBoxImg);
  mainMapDiv.appendChild(mapBoxDiv);
}


/****************************************************
 * Fügt der aktuellen Karte einen Karten-Punkt      *
 * hinzu                                            *
 * Argumente: Name oder Nummer des Punktes          *
 ****************************************************/
function drawMapPoint(placeName)
{
  var placeNumber = searchPlace(placeName);
  if (placeNumber == -1)
    return false;
  
  // Kartengrenzen holen
  var mapCoords = new Object();
  getMapCoords(mapCoords, currentMap);         
  
  var point = new Object();
  getPointCoord(point,placeNumber);
  
  var mapHeight = defaultMapY;
  if (typeof currentMap.height != 'undefined')
    mapHeight = currentMap.height;
  var left   = (point.left-mapCoords.left)     * defaultMapX / (mapCoords.right-mapCoords.left) - 4;  // -4, weil der Punkt 8x8 Pixel groß ist!
  var top    = (point.top -mapCoords.top)      * mapHeight / (mapCoords.bottom-mapCoords.top) - 4;

  var mapPointImg = new Image();
  var mapPointDiv = document.createElement("div");
  mapPointDiv.id = "mapPointDiv" + placeNumber;   
  mapPointDiv.style.position   = "absolute";
  mapPointDiv.style.top        = top  + "px";
  mapPointDiv.style.left       = left + "px";
  
  // gibt es einen Link zu diesem Kartenpunkt?
  if ( typeof(places[placeNumber].link) != 'undefined' )
  {
    mapPointDiv.style.cursor     = "pointer";
    mapPointDiv.onclick = function() {  // _gaq.push(['_trackEvent', 'mapLink', 'clicked', places[placeNumber].name]);
                                        parent["Main"].location.href = places[placeNumber].link; 
                                     };
  }
  
  mapPointImg.src   = symbolsDir + "red_pog_8px.png";
  mapPointImg.title = places[placeNumber].name;
  
  mapPointDiv.appendChild(mapPointImg);
  mainMapDiv.appendChild(mapPointDiv);
}


/****************************************************
 * Schreibt die Koordinaten der Kartengrenzen aus   *
 * der maps[]-Struktur in ein Object.               *
 * Grad-Koordinaten werden in dezimal umgerechnet   *
 * Argumente:                                       *
 ****************************************************/
// BUGME: evtl. bei Kartengrenzen left-right/top-bottom vertauschen, wenn negative Differenz 
function getMapCoords(mapCoords, map)
{
  if (typeof map.longL == 'number')
    mapCoords.left   = map.longL;
  else if (typeof map.longL == 'object')
  {
    mapCoords.left     = map.longL[0]; 
    if (typeof map.longL[1] != 'undefined')
      mapCoords.left  += map.longL[1]/60;  
    if (typeof map.longL[2] != 'undefined')
      mapCoords.left  += map.longL[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem longL bei Karte: " + map.name + "\n");   

  if (typeof map.longR == 'number')
    mapCoords.right  = map.longR;
  else if (typeof map.longL == 'object')
  {
    mapCoords.right    = map.longR[0]; 
    if (typeof map.longR[1] != 'undefined')
      mapCoords.right += map.longR[1]/60;  
    if (typeof map.longR[2] != 'undefined')
      mapCoords.right += map.longR[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem longR bei Karte: " + map.name + "\n");   

  if (typeof map.latT == 'number')
    mapCoords.top  = map.latT;
  else if (typeof map.latT == 'object')
  {
    mapCoords.top    = map.latT[0]; 
    if (typeof map.latT[1] != 'undefined')
      mapCoords.top += map.latT[1]/60;  
    if (typeof map.latT[2] != 'undefined')
      mapCoords.top += map.latT[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem latT bei Karte: " + map.name + "\n");   

  if (typeof map.latB == 'number')
    mapCoords.bottom = map.latB;
  else if (typeof map.latB == 'object')
  {
    mapCoords.bottom    = map.latB[0]; 
    if (typeof map.latB[1] != 'undefined')
      mapCoords.bottom += map.latB[1]/60;  
    if (typeof map.latB[2] != 'undefined')
      mapCoords.bottom += map.latB[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem latB bei Karte: " + map.name + "\n");   
}


/****************************************************
 * Schreibt die Koordinate eines Punktes aus        *
 * der places[]-Struktur in ein Object.             *
 * Grad-Koordinaten werden in dezimal umgerechnet   *
 * Argumente:                                       *
 ****************************************************/
function getPointCoord(place, placeNumber)
{
  if (typeof places[placeNumber].longL == 'number')
    place.left   = places[placeNumber].longL;
  else if (typeof places[placeNumber].longL == 'object')
  {
    place.left     = places[placeNumber].longL[0]; 
    if (typeof places[placeNumber].longL[1] != 'undefined')
      place.left  += places[placeNumber].longL[1]/60;  
    if (typeof places[placeNumber].longL[2] != 'undefined')
      place.left  += places[placeNumber].longL[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem longL bei Punkt: " + places[placeNumber].name + "\n");   

  
  if (typeof places[placeNumber].latT == 'number')
    place.top  = places[placeNumber].latT;
  else if (typeof places[placeNumber].latT == 'object')
  {
    place.top    = places[placeNumber].latT[0]; 
    if (typeof places[placeNumber].latT[1] != 'undefined')
      place.top += places[placeNumber].latT[1]/60;  
    if (typeof places[placeNumber].latT[2] != 'undefined')
      place.top += places[placeNumber].latT[2]/3600;  
  } 
//  else
//    DebugOut("Koordinatenproblem latT bei Point: " + places[placeNumber].name + "\n");   

}


/****************************************************
 * lässt ein mapItem blinken                        *
 * Argumente:                                       *
 ****************************************************/
function mapItemBlink(itemNumber, stage, num)
{
  var mapNumber   = searchMap(itemNumber);
  var placeNumber = searchPlace(itemNumber);
  if ((mapNumber == -1) && (placeNumber == -1))
  {
//    DebugOut ("mapItemBlink: Item " + itemNumber + " not found!\n");
    return false;
  }
  
  var obj;
  if (mapNumber != -1)
    obj = document.getElementById("mapDivNew" + mapNumber);
  else
    obj = document.getElementById("mapPointDiv" + placeNumber);
  
  if (stage <= 100)
    setOpacity(obj,stage);
  else
    setOpacity(obj,200-stage);

  stage += 10;
  if (stage > 200)
    stage = 0;
  
  blinkTimeoutID[num] = window.setTimeout (function(){mapItemBlink(itemNumber,stage,num);},FadeInterval)


  //MapDiv.style.borderColor = "#F" + stage + stage;
}


/* Setzt die Transparenz eines Objektes */
function setOpacity(obj, opacity) 
{
  opacity = (opacity > 100)?99.999:opacity;

  // IE/Win
  obj.style.filter = "alpha(opacity:"+opacity+")";

  // Safari<1.2, Konqueror
  obj.style.KHTMLOpacity = opacity/100;

  // Older Mozilla and Firefox
  obj.style.MozOpacity = opacity/100;

  // Safari 1.2, newer Firefox and Mozilla, CSS3
  obj.style.opacity = opacity/100;
}


// BUGME: einzeichnen von "Unter-Maps" implementieren!
function enlargeMap(mapNumber, Step)
{
  var mapDivNew = document.getElementById ("mapDivNew" + mapNumber);
  var mapImgNew = document.getElementById("mapImageNew" + mapNumber); 
//  var mapImg    = document.getElementById("mapImage");

  if (Step == undefined) Step = 0;

  //DebugOut ("--- " + Step + "\n");

  // Blinken stoppen, Rahmen ein
  if (Step == 0)
  {
    mapDivNew.onclick = "";

    clearTimeout (blinkTimeoutID);  // BUGME
    setOpacity(mapDivNew,100);
    mapDivNew.style.zIndex = 1000;

    //DebugOut ("zu vergrößernde Karte: " + mapDivNew.id + " (" + mapDivNew.name + ") \n");

    //DebugOut ("alte width: " + mapImgNew.width + "; height:" + mapImgNew.height + "\n"); 
    //DebugOut ("neue width: " + mapImg.width    + "; height:" + mapImg.height    + "\n"); 
    mapImgNew.oldWidth  = mapImgNew.width;   
    mapImgNew.oldHeight = mapImgNew.height;   
    mapImgNew.diffWidth  = mainMapImg.width  - mapImgNew.width;   
    mapImgNew.diffHeight = mainMapImg.height - mapImgNew.height;   
    //DebugOut ("diff width: " + mapImgNew.diffWidth    + "; height:" + mapImgNew.diffHeight    + "\n");

    //DebugOut ("alte leftP: " + mapDivNew.style.left + "; topP:" + mapDivNew.style.top + "\n"); 
    //DebugOut ("neue leftP: " + (-2)    + "; topP:" + (-2)    + "\n");   
    mapDivNew.diffLeft = parseInt(mapDivNew.style.left) - (-2);  
    mapDivNew.diffTop  = parseInt(mapDivNew.style.top)  - (-2);
    //DebugOut ("diff leftP: " + mapDivNew.diffLeft    + "; topP:" + mapDivNew.diffTop    + "\n");
   
    // Kartenbild einfügen 
    mapImgNew.src = maps[mapNumber].src;    


    //DebugOut ("-\n");

  }

  if (Step <= EnlargeSteps) 
  {
    mapDivNew.style.left = ((-2) + mapDivNew.diffLeft * (1- Step/EnlargeSteps)) + "px";
    mapDivNew.style.top  = ((-2) + mapDivNew.diffTop  * (1- Step/EnlargeSteps)) + "px";
    //DebugOut ("new leftP: " + mapDivNew.style.left + "; topP:" + mapDivNew.style.top + "\n");

    mapImgNew.width  = mapImgNew.oldWidth  + mapImgNew.diffWidth  * Step/EnlargeSteps;
    mapImgNew.height = mapImgNew.oldHeight + mapImgNew.diffHeight * Step/EnlargeSteps;
    //DebugOut ("new width: " + mapImgNew.width + "; height:" + mapImgNew.height + "\n");
  }

  // letzter Schritt
  if (Step < EnlargeSteps)
    window.setTimeout (function(){enlargeMap(mapNumber, Step+1)} , EnlargeInterval);
  else
  {
    var i;
    var oldMapNumber = searchMap(mainMapImg.title);
    var place,map;
    
    // alle mapItems entfernen
    if (typeof maps[oldMapNumber].places != 'undefined')
    {
      for (i=0; i<maps[oldMapNumber].places.length; i++)
      {
        place = searchPlace(maps[oldMapNumber].places[i]);
        mainMapDiv.removeChild(document.getElementById("mapPointDiv"+place));
      }
    }
    if (typeof maps[oldMapNumber].childMaps != 'undefined')
    {
      for (i=0; i<maps[oldMapNumber].childMaps.length; i++)
      {
        map = searchMap(maps[oldMapNumber].childMaps[i]);
        // die gerade vergrößerte Karte nicht entfernen!
        if (map != mapNumber)
          mainMapDiv.removeChild(document.getElementById("mapDivNew"+map));
      }
    }
  
    // Hauptkarte austauschen
    mainMapImg.src   = maps[mapNumber].src;
    mainMapImg.title = maps[mapNumber].name;
    mainMapDiv.onclick = function() {reduceMap(RM_STATE_START);};
    
    var i;
    if (typeof maps[mapNumber].places != 'undefined')
    {
      for (i=0; i<maps[mapNumber].places.length; i++)
        drawMapPoint(mapNumber, maps[mapNumber].places[i]);
    }
    
  //for (i=0; i<maps[mapNumber].childMaps.length; i++)
  //  drawMapBox(maps[mapNumber].childMaps[i]);
 
    window.setTimeout (function(){fadeoutBorder(mapNumber,90)}, FadeInterval);    
  }
}

function fadeoutBorder(mapNumber,Stage)
{
  var mapBoxDiv = document.getElementById ("mapDivNew" + mapNumber);

  setOpacity(mapBoxDiv,Stage);
  
  if (Stage > 0)
    window.setTimeout (function(){fadeoutBorder(mapNumber,Stage-10)}, FadeInterval); 
  else
  {
    mapBoxDiv.removeChild(document.getElementById("mapImageNew" + mapNumber)); 
    mainMapDiv.removeChild(mapBoxDiv); 
  }
}

var RM_STATE_START  = 1;
var RM_STATE_FADE   = 2;

function reduceMap(state)
{
  var mapNumberOld = searchMap(mainMapImg.title);
  var mapNumberNew = searchMap(maps[mapNumberOld].parentMap);

//  DebugOut ("Reduce state: " + state + " (" + mainMapImg.title + "; Nr. " + mapNumberOld + ")!\n");
  
  if (state == RM_STATE_START)
  {  
    var oldBoxImg = new Image();  
    var oldBoxDiv = document.createElement("div");
    oldBoxDiv.id = "mapDivOld" + mapNumberOld;
    oldBoxDiv.style.position    = "absolute";
    oldBoxDiv.style.top         = "0px";
    oldBoxDiv.style.left        = "0px";
    //oldBoxDiv.style.border      = boxBorderWidth + "px";
    //oldBoxDiv.style.borderColor = boxBorderColor;
    //oldBoxDiv.style.borderStyle = "solid";
    oldBoxImg.src    = maps[mapNumberOld].src;
    // BUGME: auf in der Kartenstrutur angegeben Höhe beziehen
    oldBoxImg.width  = defaultMapX;
    oldBoxImg.height = defaultMapY;
    mainMapImg.src = maps[mapNumberNew].src;
     
    oldBoxDiv.appendChild(oldBoxImg);
    mainMapDiv.appendChild(oldBoxDiv);

    // alle mapItems entfernen
    var i;
    if (typeof maps[mapNumberOld].places != 'undefined')
    {
      for (i=0; i<maps[mapNumberOld].places.length; i++)
      {
        place = searchPlace(maps[mapNumberOld].places[i]);
        mainMapDiv.removeChild(document.getElementById("mapPointDiv"+place));
      }
    }
    if (typeof maps[mapNumberOld].childMaps != 'undefined')
    {
      for (i=0; i<maps[mapNumberOld].childMaps.length; i++)
      {
        map = searchMap(maps[mapNumberOld].childMaps[i]);
        mainMapDiv.removeChild(document.getElementById("mapDivNew"+map));
      }
    }
    
    fade (oldBoxDiv, 100, -10, EnlargeInterval);
  }
  else if (state == RM_STATE_FADE)
  {
  }
//  else
//    DebugOut ("reduceMap: unknown state!\n");
}

function fade(obj, step, stepSize, Interval)
{
  setOpacity(obj, step);
  
  step += stepSize; 
  if (step < 0)
  {
    var parent = obj.parentNode;
    parent.removeChild(obj);
    return;
  }
  if (step > 100)
    return;  
    
  window.setTimeout (function() {fade(obj, step, stepSize, Interval);}, Interval);
}



function Maus()
{
  // DebugOut ("Maus!!!\n");
}

