/*
 *  Navigation scripts for the Canadian Wind Energy Atlas
 *  (c) Copyright 2003 Environment Canada
 *
 *  by Marc-Andre Disnard, Ecole polytechnique de Montreal, December 2003
 *  revised by inVisu inc., 2004
 *  revised by inVisu inc., 2008
 *
 */


var isReady = false;            // Internally set to 'true' when page is done loading.
var curField = defaultField;
var curHeight = defaultHeight;
var curSeason = defaultSeason;

var hasUp    = 0;               // Neighboring tile number in each direction, 0 for none.
var hasDown  = 0;               // (set dynamically, so we initialize it to 0).
var hasLeft  = 0;
var hasRight = 0;

var subTileX   = 0;             // Current sub-tile indices for the micro-level.
var subTileY   = 0;

var tileExists = true;          // Image for current tile exists? (dynamic)

var popupRosewind = 0;  // Stores the window used to display wind roses
var popupObsStation = 0;  // Stores the window used to display observation comparisons

// Browser-independant, returns the DHTML <SPAN> element for the specified ID.
function getSpan(id) {
   if (document.all)
      return document.all[id];
   if (document.layers)
      return document.layers[id];
   if (document.getElementById)
      return document.getElementById(id);
   return null;
}

// Browser-independant, returns the DHTML <SPAN> element's style for the specified ID.
function getSpanStyle(id) {
   if (document.layers)
      return document.layers[id];
   if (document.all) {
      var s = document.all[id];
      if (s && s.style)
         return s.style;
   }
   if (document.getElementById) {
      var s = document.getElementById(id);
      if (s && s.style)
         return s.style;
   }
   return null;
}

// Called when the page is done loading, we then set up dynamic stuff.
// Also, this function is implicitly called by "setLoc()".
function pageLoaded() {
   isReady = true;
   document.images['navMap'].onmousemove = mouseMove;
   //    document.images['navMap'].onmouseout = mouseOut;

   // Switch overlay images if they are enabled...
   for (v in overFlags) {
      document.images['img' + v].onmousemove = mouseMove;
      // document.images['img' + v].onmouseout = mouseOut;
   }
   changeMap();
}

// Called when the page is resized -- needed to adjust overlay positions.
function pageResized() {
   if (!isReady)
      return;
   changeOverlay();
}

// Browser-independant, updates the hidden input field 'no' with a new tile number.
function setTileNo(newNo) {
   tileNo = newNo;

   // This should work with MSIE...
   if (document.forms && document.forms[0] && document.forms[0].elements) {
      if (document.forms[0].elements.no && document.forms[0].elements.no.value) {
         document.forms[0].elements.no.value = tileNo;
         document.forms[1].elements.no.value = tileNo;
         return;
      }
   }

   // This could work with other browsers...
   if (document.getElementById) {
      var f = document.getElementById("dummy");
      if (f && f.no) {
         f.no.value = tileNo;
         return;
      }
   }
}

// Changes the current map image and updates all necessary stuff (variables, interface, navigation, ...)
function changeMap() {
   var suffix = String(parseInt(tileNo, 10));
   while (3 > suffix.length)
      suffix = "0" + suffix;
   var subX = String(parseInt(subTileX, 10));
   while (2 > subX.length)
      subX = "0" + subX;
   var subY = String(parseInt(subTileY, 10));
   while (2 > subY.length)
      subY = "0" + subY;

   refreshFlags();

   // switch to blank image before, to avoid strange effects in some browsers...
   document.images['navMap'].src = '../images/blank-overlay.gif';

   // Switch main map image.
   if(hasHeight[curField])
      document.images['navMap'].src = (tileExists)? (fieldDirs[curField] + "/" + seasonDir[curSeason]  + "/" + heightDir[curHeight] + "/tile" + suffix + ".png") : "../images/no-data.png";
   else
      document.images['navMap'].src = (tileExists)? (fieldDirs[curField] + "/tile" + suffix + ".png") : "../images/no-data.png";

   // Update legend and minimap...
   var legend;
   if (hasHeight[curField])
      legend = "../images/legend_" + curField + "_" + curHeight + ".gif";
   else
      legend = "../images/legend_" + curField + ".gif";

   document.images['legend'].src  = legend;
   document.images['minimap'].src = "../minimap/mini" + ((tileExists)?suffix:'000') + ".png";

   // Enable or disable arrow images according to neighbor info.
   document.images['topArrow'].src    = "../images/top-arrow" +    (hasUp ?    ".gif" : "-off.gif");
   document.images['bottomArrow'].src = "../images/bottom-arrow" + (hasDown ?  ".gif" : "-off.gif");
   document.images['leftArrow'].src   = "../images/left-arrow" +   (hasLeft ?  ".gif" : "-off.gif");
   document.images['rightArrow'].src  = "../images/right-arrow" +  (hasRight ? ".gif" : "-off.gif");

   // Update caption with quadrangle and (j,i) coordinates.
   var span = getSpan('spicAndSpan');
   if (span)
   {
      var title =  "Quadrangle " + quads[tileNo] + " (j=" + jCoordz[tileNo] + "; i=" + iCoordz[tileNo] + ") - " + fieldName[curField];
      if ( hasHeight[curField] ) {
         title += " - " + heightName[curHeight];
         title += " - " + seasonName[curSeason];
      }
      span.innerHTML = title;
   }

   changeOverlay();

   setRadios();
   setBoxes();
}

// Enables/disables radio buttons for season and height selection.
function setRadios() {
   var i = 0, h, s;

   // Get radio button object for height and season
   if ( document.forms && document.forms[0] && document.forms[0].elements && document.forms[0].elements.height )
      r = document.forms[0].elements.height;
   if ( !r && document.getElementById )
   {
      r = document.getElementById("dummy");
      if ( r && r.height )
         r = r.height;
      else
         r = null;
   }

   if ( document.forms && document.forms[0] && document.forms[0].elements && document.forms[0].elements.season )
      rs = document.forms[0].elements.season;
   if ( !rs && document.getElementById )
   {
      rs = document.getElementById("dummy");
      if ( rs && rs.season )
         rs = rs.season;
      else
         rs = null;
   }

   var color;
   var fontStyle;
   var isdisabled;

   if ( hasHeight[curField])
   {
      color = "#000";
      fontStyle = "normal";
      isdisabled=false;
   }
   else
   {
      color = "#999";
      fontStyle = "italic";
      isdisabled=true;
   }

   i=0;

   for( h in heightDir )
   {
      s = getSpanStyle('span' + h);
      if (s)
      {
         s['color'] = color;
         s['fontStyle'] = fontStyle;
      }
      if (r)
         r[i].disabled = isdisabled;
      i++;
   }

   i=0;

   for( s in seasonDir)
   {
      s = getSpanStyle('span' + s );
      if ( s )
      {
         s['color'] = color;
         s['fontStyle'] = fontStyle;
      }
      if (rs)
         rs[i].disabled = isdisabled;
      i++;
   }
}

// Enables/disables check-boxes for the overlay selection.
function setBoxes() {
   var i = 0, v;

   for (v in overFlags) {
      var c = null;       // For the check box.

      // Get check box object...
      if (document.forms && document.forms[0] && document.forms[0].elements && document.forms[0].elements[v])
         c = document.forms[0].elements[v];
      if (!c && document.getElementById) {
         c = document.getElementById("dummy");
         if (c && c[v])
            c = c[v];
         else
            c = null;
      }

      var s = getSpanStyle('span' + v);
      if (flagz[tileNo] & overFlags[v]) {
         if (s) {
            s['color'] = "#000";
            s['fontStyle'] = "normal";
         }
         if (c)
            c.disabled = false;
      } else {
         if (s) {
            s['color'] = "#999";
            s['fontStyle'] = "italic";
         }
         if (c)
            c.disabled = true;
      }
   }
}

// Changes the current overlay and updates all necessary stuff (variables, interface, navigation, etc.)
function changeOverlay() {
   var suffix = String(parseInt(tileNo, 10));
   while (3 > suffix.length)
      suffix = "0" + suffix;

   var x = 0, y = 0;
   var img = document.images['navMap'];

   // Get position of big map image within page.
   if (document.layers) {
      x += ('number' == typeof(img.pageX))? img.pageX : img.x;
      y += ('number' == typeof(img.pageY))? img.pageY : img.y;
   } else if (document.all || document.getElementById) {
      var parent = img;
      while (parent) {
         x += parent.offsetLeft;
         y += parent.offsetTop;
         parent = parent.offsetParent;
      }
   }

   // Argh! Lots of tweaking to get this right!
   if (document.all) {
      x += 3;
      y += 1;
   } else {
      x += 1;
      y += 1;
   }

   refreshFlags();

   // Put position of <DIV> overlays exactly over the main map.
   for (v in overFlags)
      setPos('div' + v,  x, y, options[v]);

   // switch to blank overlay before, to avoid strange effects in some browsers...
   for (v in overFlags)
      document.images['img' + v].src = '../images/blank-overlay.gif';

   // Switch overlay images if they are enabled...
   for (v in overFlags) {
      if (tileExists)
         document.images['img' + v].src = overDirs[v] + 'tile' + suffix + '.gif';
   }
}

// Updates state variables when needed (on map change, on overlay change, etc.)
function refreshFlags() {
   hasUp         = 0;
   hasDown       = 0;
   hasLeft       = 0;
   hasRight      = 0;
   tileExists    = false;

   var i, j;

   // See if current tile has left/right neighbors...
   for (i = 0; rows[i]; i++) {
      for (j = 0; rows[i][j]; j++) {
         if (rows[i][j] == tileNo) {
            tileExists = true;
            if (0 < j)
               hasLeft = rows[i][j-1];
            if (rows[i][j+1])
               hasRight = rows[i][j+1];
         }
      }
   }

   // See if current tile has up/down neighbors...
   for (i = 0; cols[i]; i++) {
      for (j = 0; cols[i][j]; j++) {
         if (cols[i][j] == tileNo) {
            tileExists = true;
            if (0 < j)
               hasDown = cols[i][j-1];
            if (cols[i][j+1])
               hasUp = cols[i][j+1];
         }
      }
   }

}

// Callback function for 'click' event on the top arrow.
function upClick() {
   if (!isReady)
      return;
   if (!hasUp)
      return;

   setTileNo(hasUp);

   setLoc();
   if (hasUp)
      upOver();
}

// Callback function for 'click' event on the bottom arrow.
function downClick() {
   if (!isReady)
      return;
   if (!hasDown)
      return;

   setTileNo(hasDown);

   setLoc();
   if (hasDown)
      downOver();
}

// Callback function for 'click' event on the left arrow.
function leftClick() {
   if (!isReady)
      return;
   if (!hasLeft)
      return;

   setTileNo(hasLeft);

   setLoc();
   if (hasLeft)
      leftOver();
}

// Callback function for 'click' event on the right arrow.
function rightClick() {
   if (!isReady)
      return;
   if (!hasRight)
      return;

   setTileNo(hasRight);

   setLoc();
   if (hasRight)
      rightOver();
}

// Callback function when the current field is modified by the user.
function setField(f) {
   if (!isReady)
      return;

   if (f != curField) {
      curField = f;
      setLoc();
   }
}

// Callback function when the current height is modified by the user.
function setHeight(h) {
   if (!isReady)
      return;

   if (h != curHeight) {
      curHeight = h;
      setLoc();
   }
}

// Callback function when the current season is modified by the user.
function setSeason(s) {
   if (!isReady)
      return;

   if (s != curSeason) {
      curSeason = s;
      setLoc();
   }
}

// Browser-independant positioning of <DIV> elements (for overlays).
function setPos(div, x, y, viz) {
   if (document.layers) {
      s = document.layers[div];
      s.left = x;
      s.top = y;
      s.visibility = (viz)? 'show' : 'hide';
   } else if (document.all) {
      s = document.all[div];
      s.style.left = x;
      s.style.top = y;
      s.style.visibility = (viz)? 'visible' : 'hidden';
   } else if (document.getElementById) {
      s = document.getElementById(div);
      s.style.left = x;
      s.style.top = y;
      s.style.visibility = (viz)? 'visible' : 'hidden';
   }
}

// Callback function when the user clicks on overlay check-buttons.
function toggleOption(o) {
   if (!isReady)
      return;

   options[o.name] = o.checked;
   setLoc();
}

// Callback function for 'click' event in the main map
function navClick(e) {
   if (!e)
      e = window.event;

   // Get the click offset in the image. Should work in all browsers...
   var x = 0, y = 0;
   var img = document.images['navMap'];

   if (e.offsetX || e.offsetY) {
      x = e.offsetX;
      y = e.offsetY;
      // calculate window scrolling correction for Mac/IE
      // http://www.macdevcenter.com/pub/a/mac/synd/2001/09/07/mac_scripting.html?page=3
      var isMac = navigator.userAgent.indexOf("Mac") != -1;
      var isMSIE = browserName=navigator.appName == "Microsoft Internet Explorer";
      if ( isMac && isMSIE )
      {
         x += document.body.scrollLeft;
         y += document.body.scrollTop;
      }
   } else {

      // Get position of nav image within page.
      if (document.layers) {
         x += ('number' == typeof(img.pageX))? img.pageX : img.x;
         y += ('number' == typeof(img.pageY))? img.pageY : img.y;
      } else if (document.all || document.getElementById) {
         var parent = img;
         while (parent) {
            x += parent.offsetLeft;
            y += parent.offsetTop;
            parent = parent.offsetParent;
         }
      }

      // Get click offset within image.
      x = e.pageX - x - img.border;
      y = e.pageY - y - img.border;
   }

   // fonctions de Sylvain:
   // ni=(iCoordz[tileNo]-2)*105/2 + x*105/512+(174-105)/2;
   // nj=(jCoordz[tileNo]-3)*105/2 + (512-y)*105/512+(174-105)/2;

   // ( (first decal on the left) + (number of tiles * width of each tile) + round(clicked point in this tile) )
   ni = ( (cfTileShavedFirsti-1) + ((iCoordz[tileNo]-2)/2) * ( cfTileShavedLasti-cfTileShavedFirsti )
          + Math.round( 1 + ( ( cfTileShavedLasti-cfTileShavedFirsti ) - 1 ) * ( x - 1 ) / ( 512 - 1 ) ) );
   nj = ( (cfTileShavedFirstj-1) + ((jCoordz[tileNo]-3)/2) * ( cfTileShavedLastj-cfTileShavedFirstj )
          + Math.round( 1 + ( ( cfTileShavedLastj-cfTileShavedFirstj ) - 1 ) * ( 512 - y ) / ( 512 - 1 ) ) );
   // Pop up roses and histograms
   popupRose( getURL(roseURL) + "&ni=" + ni + "&nj=" + nj );
}

// Callback function for 'mouseMove' event in the main map
function mouseMove(e) {
   if (!e)
      e = window.event;

   // Get the click offset in the image. Should work in all browsers...
   var x = 0, y = 0;
   var img = document.images['navMap'];

   if (e.offsetX || e.offsetY) {
      x = e.offsetX;
      y = e.offsetY;
      // calculate window scrolling correction for Mac/IE
      // http://www.macdevcenter.com/pub/a/mac/synd/2001/09/07/mac_scripting.html?page=3
      var isMac = navigator.userAgent.indexOf("Mac") != -1;
      var isMSIE = browserName=navigator.appName == "Microsoft Internet Explorer";
      if ( isMac && isMSIE )
      {
         x += document.body.scrollLeft;
         y += document.body.scrollTop;
      }
   } else {
      // Get position of nav image within page.
      if (document.layers) {
         x += ('number' == typeof(img.pageX))? img.pageX : img.x;
         y += ('number' == typeof(img.pageY))? img.pageY : img.y;
      } else if (document.all || document.getElementById) {
         var parent = img;
         while (parent) {
            x += parent.offsetLeft;
            y += parent.offsetTop;
            parent = parent.offsetParent;
         }
      }

      // Get click offset within image
      x = e.pageX - x - img.border;
      y = e.pageY - y - img.border;
   }

   // fonctions de Sylvain:
   // i=iCoordz[tileNo];
   // j=jCoordz[tileNo];
   // ni=Math.round(105*(i-2)/2+174/2+105*(x/512-.5));
   // nj=Math.round(105*(j-3)/2+174/2-105*(y/512-.5));

   // ( (first decal on the left) + (number of tiles * width of each tile) + round(clicked point in this tile) )
   ni = ( (cfTileShavedFirsti-1) + ((iCoordz[tileNo]-2)/2) * ( cfTileShavedLasti-cfTileShavedFirsti )
          + Math.round( 1 + ( ( cfTileShavedLasti-cfTileShavedFirsti ) - 1 ) * ( x - 1 ) / ( 512 - 1 ) ) );
   nj = ( (cfTileShavedFirstj-1) + ((jCoordz[tileNo]-3)/2) * ( cfTileShavedLastj-cfTileShavedFirstj )
          + Math.round( 1 + ( ( cfTileShavedLastj-cfTileShavedFirstj ) - 1 ) * ( 512 - y ) / ( 512 - 1 ) ) );

   ll = llfninj(ni,nj);

   var span = getSpan('spaninfo');
   if (span)
   {
      span.innerHTML = "Lat.=" + Math.round(1000 * ll[0])/1000 + "&nbsp;Long.=" + Math.round(1000*ll[1])/1000;
   }
}

function mouseOut(e) {

   if (!e)
      e = window.event;

   var span = getSpan('spaninfo');
   if (span)
   {
      span.innerHTML = "x=N/A</BR>y=N/A<BR>lat=N/A<BR>long=N/A";
   }
}

function getRose() {
   lat=document.getElementById("latlongform").lat.value;
   lon=document.getElementById("latlongform").lon.value;
   postal=document.getElementById("latlongform").postal.value;

   // s'il n'y a pas de code postal, on cherche le numéro de tuile ici,
   // sinon la recherche du numéro de tuile sera faite par rose.php
   if ( postal == "" )
   {
      ninj = ninjfll(lat,lon);
      ni=eval(ninj[0]);
      nj=eval(ninj[1]);

      //BO i= 2 * Math.floor((ni-(174-105)/2) / 105)+2;
      //BO j= 2 * Math.floor((nj-(174-105)/2) / 105)+3;

      //var img = document.images['navMap'];
      //img_dim=('number' == typeof(img.pageX))? img.pageX : img.x;

      // Go to new location
      // compute iCoord and jCoord
      ic = 2 + 2 * Math.floor( ( ni - cfTileShavedFirsti ) / ( cfTileShavedLasti-cfTileShavedFirsti ) );
      jc = 3 + 2 * Math.floor( ( nj - cfTileShavedFirstj ) / ( cfTileShavedLastj-cfTileShavedFirstj ) );
      // look for that tile in iCoordz and jCoordz
      var i, found = 0;
      for ( i = 1 ; i <= 65 ; ++i )
      {
         if ( iCoordz[i] == ic && jCoordz[i] == jc )
         {
            found = i;
            break;
         }
      }
      // if found, go to it
      if (found) {
         setTileNo(found);
         setLoc();
      }
      // Pop up roses and histograms
      popupRose( getURL(roseURL) + "&ni=" + ni + "&nj=" + nj );
   }
   else
   {
      // Pop up roses and histograms
      popupRose( getURL(roseURL) + "&postal=" + postal );
   }
}

// Callback function for 'click' event in the minimap, changes the current tile number.
function miniClick(e) {
   if (!e)
      e = window.event;

   // Get the click offset in the image. Should work in all browsers...
   var x = 0, y = 0;
   if (e.offsetX && e.offsetY) {
      x = e.offsetX;
      y = e.offsetY;
   } else {
      var img = document.images['minimap'];

      // Get position of minimap within page.
      if (document.layers) {
         x += ('number' == typeof(img.pageX))? img.pageX : img.x;
         y += ('number' == typeof(img.pageY))? img.pageY : img.y;
      } else if (document.all || document.getElementById) {
         var parent = img;
         while (parent) {
            x += parent.offsetLeft;
            y += parent.offsetTop;
            parent = parent.offsetParent;
         }
      }

      // Get click offset within image.
      x = e.pageX - x;
      y = e.pageY - y;
   }

   // See if the user clicked inside a minitile...
   var i, found = 0;
   for (i = 0; minitiles[i]; i++) {
      if (x >= minitiles[i][1] && x <= minitiles[i][3] && y >= minitiles[i][2] && y < minitiles[i][4])
      {
         found = minitiles[i][0];
         break;
      }
   }
   if (found) {
      setTileNo(found);
      setLoc();
   }
}

// Returns an URL for the current image/overlay/options and stuff.
function getURL(base) {
   var url = base + "?field=" + curField + "&height=" + curHeight + "&season=" + curSeason + "&no=" + tileNo;
   for (v in overFlags) {
      if (options[v])
         url += '&' + v + '=1';
   }
   return url;
}

// Callback function for update button. Updates the location in the location bar.
// Updating the "window.location" calls "pageLoaded()" which, in turn, calls "changeMap()"
function setLoc() {
   window.location = getURL(baseURL);
}

// Callback function for 'click' event on the cart-add button:
function cartAdd() {
   // We call ourselves with a special flag...
   if (tileExists)
      window.location = getURL(baseURL) + "&add=yes";
}

function obsLaunch()
{
   // We call ourselves with a special flag...
   if (tileExists) {
      url = getURL(obsURL) + "&tile=" + tileNo;
      if(!popupObsStation || popupObsStation.closed)
         popupObsStation = open(url,"","resizable=yes,scrollbars=yes,width=810,height=750");
      else {
         popupObsStation.close();
         popupObsStation = open(url,"","resizable=yes,scrollbars=yes,width=810,height=750");
         // popupObsStation.location.href = url;
         // popupObsStation.focus();
      }
   }
}

// Callback function for 'click' event on the cart-del button:
function cartDel() {
   // We call ourselves with a special flag...
   if (tileExists)
      window.location = getURL(baseURL) + "&del=yes";
}

// Callback function for 'click' event on the cart-view button:
function cartView() {
   // We call ourselves with a special flag...
   if (tileExists)
      window.location = getURL(cartURL) + "&view=yes";
}

// Mouse-over callback functions for navigation arrows:
function upOver() {if (hasUp) document.images['topArrow'].src = "../images/top-arrow-over.gif";}
function downOver() {if (hasDown) document.images['bottomArrow'].src = "../images/bottom-arrow-over.gif";}
function leftOver() {if (hasLeft) document.images['leftArrow'].src = "../images/left-arrow-over.gif";}
function rightOver() {if (hasRight) document.images['rightArrow'].src = "../images/right-arrow-over.gif";}

// Mouse-out callback functions for navigation arrows:
function upOut() {if (hasUp) document.images['topArrow'].src = "../images/top-arrow.gif";}
function downOut() {if (hasDown) document.images['bottomArrow'].src = "../images/bottom-arrow.gif";}
function leftOut() {if (hasLeft) document.images['leftArrow'].src = "../images/left-arrow.gif";}
function rightOut() {if (hasRight) document.images['rightArrow'].src = "../images/right-arrow.gif";}

function getbigmap(field, season, height)
{
   var url;
   if ( hasHeight[field] )
      url = "../images/bigmap_" + field + "_" + season + "_" + height + ".png";
   else
      url = "../images/bigmap_" + field + ".png";
   popup(url, "_blank", 520, 393);
}

function popup(mylink, windowname, width, height)
{
   if (! window.focus)return true;
   var href;
   if (typeof(mylink) == 'string')
      href=mylink;
   else
      href=mylink.href;
   window.open( href, windowname, 'width=' + width + ',height=' + height + ',toolbar=no,menubar=no,scrollbars=yes');
   return false;
}

function popupRose( roseWind_url )
{
   if(!popupRosewind || popupRosewind.closed)
      popupRosewind = open(roseWind_url,"","resizable=no,width=750,height=650");
   else {
      popupRosewind.close();
      // popupRosewind.location.href = roseWind_url;
      // popupRosewind.focus();
      popupRosewind = open(roseWind_url,"","resizable=no,width=750,height=650");
   }
   //popupRosewind.title = roseWind_url;
}
