/*

  Copyright © 2006..2008  Alex Tingle

*/

var FLD ={
  DEFAULT_SLR : 7,
  DEFAULT_TYPE : 0,
  SET_LINK_TEXT : true,
  IS_PNG : false,
  OPACITY : 1,

  map : null,
  SCRIPT_NAME : document.URL.replace(/[?].*$/,''),
  SERVER_NAME : document.URL.replace(/^https?:[/][/]/,'').replace(/[/].*$/,''),
  tileBaseUrl : '/floodtile/',
  mapTypesArray : [], ///< An array of 'mapTypes'
  overlaysArray : [],
  seaLevelRise : 7,
  whichType : 0, ///< 0=map 1=sat
  
  /** Callback for user actions. */
  onchange : null,

  /** Read GET parameters and set up the environment. Call once FLD.map
   *  has been set.
   *  Initialises FLD.mapTypesArray & FLD.overlaysArray.
   *  Sets the initial lng,lat, zoom & slr (defaults provided by args).
   *  Returns the params object.
   */
  initialize : function(lng,lat,zoom)
    {
      // Set default values, after ALL javascript has been loaded.
      // Allows for subsequent .js to change default values.
      FLD.seaLevelRise=FLD.DEFAULT_SLR;
      FLD.whichType=FLD.DEFAULT_TYPE;

      // Read GET params.
      var params=FLD.get_parameters();
      if(params)
      {
        if(params['ll'])
        {
          var yx=params['ll'].split(',');
          if(yx.length==2)
          {
            lat=parseFloat(yx[0]);
            lng=parseFloat(yx[1]);
          }
        }
        if(params['m'])
          FLD.seaLevelRise=Math.abs(parseInt(params['m'],10));
        if(params['z'])
          zoom=Math.abs(parseInt(params['z'],10));
        if(params['t'])
          FLD.whichType=Math.abs(parseInt(params['t'],10));
      }

      // Get map types (and limit their resolution to that of the flood tiles.
      FLD.mapTypesArray=FLD.map.getMapTypes();
      for(var i=0, ilen=FLD.mapTypesArray.length; i<ilen; ++i)
      {
        FLD.mapTypesArray[i].getMaximumResolution = function() {return 17;}
      }

      // Make overlays for each sea level.
      var select=document.getElementById('m');
      if(select)
      {
        for(var j=0, jlen=select.options.length; j<jlen; ++j)
        {
          var slr = parseInt( select.options[j].value, 10 );
          FLD.overlaysArray.push(
            new GTileLayerOverlay(new FLD.FloodTileLayer(slr))
          );
        }
      }
      else
      {
        // Just one slr.
        FLD.overlaysArray.push(
          new GTileLayerOverlay(new FLD.FloodTileLayer(FLD.seaLevelRise))
        );
      }

      FLD.map.setCenter(
        new GLatLng(lat,lng),
        17-zoom,
        FLD.mapTypesArray[FLD.whichType]
      );

      // Set the starting level to match the selected option in the HTML.
      FLD.setSeaLevelRise(FLD.seaLevelRise,true);
      
      return params;
    },

  /** Looks at FLD.map and works out which map type it's set to.
   *  Sets FLD.whichType, and calls FLD.setLink() if it's changed. */
  readWhichType : function()
    {
      var mt=FLD.map.getCurrentMapType();
      if(mt!=FLD.mapTypesArray[FLD.whichType])
      {
        for(var i=0; i<FLD.mapTypesArray.length; i++)
          if(mt==FLD.mapTypesArray[i])
          {
            FLD.whichType=i;
            break;
          }
        FLD.setLink();
      }
    },

  /** Callback from HTML - called when the user changes SLR. */
  setSeaLevelRise : function(slr,init)
    {
      var select=document.getElementById('m');
      if(!init)
        FLD.map.removeOverlay(FLD.overlaysArray[FLD.seaLevelRiseIdx]);
      if(select)
      {
        // Find the nearest matching option (round down).
        var m, i=select.options.length;
        do{
            m = parseInt( select.options[ --i ].value, 10 );
        } while( m>slr && i );
        FLD.seaLevelRiseIdx = i;
        FLD.seaLevelRise = m;
        FLD.map.addOverlay(FLD.overlaysArray[i]);
        select.selectedIndex = i;
        select.className = 'm'+m;
      }
      else
      {
        FLD.seaLevelRiseIdx = 0;
        FLD.seaLevelRise = slr;
        FLD.map.addOverlay(FLD.overlaysArray[0]);
      }
      FLD.setLink();
    },

  /** Callback from various places - called when something changes.
   *  Sets the value of #link. */
  setLink : function()
    {
      // Call user callback.
      if(FLD.onchange)
        FLD.onchange();
      // Update the #link element
      var link =document.getElementById('link');
      if(!link)
        return;
      var center =FLD.map.getCenter();
      link.href=FLD.SCRIPT_NAME+'?ll='+center.lat().toFixed(4)+','+
                                       center.lng().toFixed(4);
      if(FLD.map.getZoom()!=6)
        link.href+='&z='+(17-FLD.map.getZoom());
      if(FLD.seaLevelRise!=FLD.DEFAULT_SLR)
        link.href+='&m='+FLD.seaLevelRise;
      if(FLD.whichType!=FLD.DEFAULT_TYPE)
        link.href+='&t='+FLD.whichType;
      if(FLD.SET_LINK_TEXT)
      {
        link.innerHTML=link.href;
        FLD.flash(link);
      }
    },

  //
  //  UTILS
  //

  WindowOnload : function(f)
    {
      var prev=window.onload;
      window.onload=function(){ if(prev)prev(); f(); }
    },

  /** Generate a params object from the current URL's GET parameters. */
  get_parameters : function()
    {
      var url = window.location.href;
      var paramsStart = url.indexOf("?");

      if(paramsStart != -1)
      {
        var paramString = url.substr(paramsStart + 1);
        var params = paramString.split("&");
        for(var i=0, len=params.length; i<len; ++i)
        {
          var pairArray = params[i].split("=");
          if(pairArray.length == 2)
              params[pairArray[0]] = pairArray[1];
        }
        return params;
      }
      return null;
    },

  /** If params[key] is set, then return its 'truthiness',
   *  otherwise return dflt. */
  isSet : function(params,key,dflt)
    {
      if( params && params.hasOwnProperty(key) )
      {
        var v =params[key];
        return !( v==='0' || v==='off' || v===0 || v===false );
      }
      return dflt;
    },

  /** Briefly flash an element. */
  flash : function(e,col)
    {
      col = col? col: 'FFD700';
      if(e.fld_flash_tid)
      {
        clearTimeout(e.fld_flash_tid);
        e.fld_flash_tid=0;
      }
      var STEPS=10;
      var R =parseInt(col.substr(0,2),16);
      var G =parseInt(col.substr(2,2),16);
      var B =parseInt(col.substr(4,2),16);
      var r = (255-R)/STEPS;
      var g = (255-G)/STEPS;
      var b = (255-B)/STEPS;
      var i = 0;
      function hex(n,len)
        {
          len=len?len:2;
          var result=(Math.floor(n)).toString(16);
          while(result.length<len)
            result='0'+result;
          return result;
        }
      function next()
        {
          if(i>=STEPS)
          {
            e.style.backgroundColor='#fff';
            e.fld_flash_tid=0;
            return;
          }
          var rgb = '#' + hex(R+i*r) + hex(G+i*g) + hex(B+i*b);
          e.style.backgroundColor=rgb;
          i++;
          e.fld_flash_tid=setTimeout(next,150);
        }
      next();
    },

  /** Returns TRUE if the adsense ad-unit has been blocked. */
  adsenseBlocked : function()
    {
      var div=document.getElementById('adunit');
      var iframes=div.getElementsByTagName('iframe');
      if(!iframes || 0==iframes.length)
        return true;
      for(var i=0, len=iframes.length; i<len; i++)
      {
        var e=iframes[i];
        if((e.src.indexOf('googlesyndication.com') > -1) &&
           (e.setAttribute && (e.style.visibility=='hidden' ||
            e.style.display=='none')))
        {
          return true;
        }
      }
      return false;
    },

  /** Calculate the absolute y-coordinate of obj. */
  findPosY : function(obj)
    {
      var curtop = 0;
      if(obj.offsetParent)
          while(1)
          {
            curtop += obj.offsetTop;
            if(!obj.offsetParent)
              break;
            obj = obj.offsetParent;
          }
      else if(obj.y)
          curtop += obj.y;
      return curtop;
    }

}; // end FLD


// Google Maps stuff - depends on Google's Maps API.
if((typeof GMap2)!='undefined')
{

  // Copyrights
  FLD.copyCollection = new GCopyrightCollection('firetree.net');
  FLD.copyright =
      new GCopyright(
        354,
        new GLatLngBounds(new GLatLng(-90,-180), new GLatLng(90, 180)),
        0,
        "&copy;2006, 2007 Alex Tingle"
      );
  FLD.copyCollection.addCopyright(FLD.copyright);


  /**
   *   class FloodTileLayer.
   *   Custom GTileLayer for flood maps.
   */
  FLD.FloodTileLayer = function(slr)
  {
    this.slr=slr;
  }
  FLD.FloodTileLayer.prototype = new GTileLayer(FLD.copyCollection,0,17);
  FLD.FloodTileLayer.prototype.getTileUrl = function(tile,zoom)
  {
    var sep='/';
    var eq='_';
    return 'http://'+FLD.SERVER_NAME+FLD.tileBaseUrl
      +"m"+eq+this.slr+sep
      +"x"+eq+tile.x+sep
      +"y"+eq+tile.y+sep
      +"zoom"+eq+(17-zoom);
  }
  FLD.FloodTileLayer.prototype.isPng = function()
  {
    // IE ignores the opacity if this is set to true.
    return FLD.IS_PNG;
  }
  FLD.FloodTileLayer.prototype.getOpacity = function()
  {
    return FLD.OPACITY;
  }


  /**
   *   class BlockControl.
   *   Custom GControl that just uses a pre-existing element.
   */
  FLD.BlockControl = function(element)
  {
    this.element=element;
  }
  FLD.BlockControl.prototype=new GControl();
  FLD.BlockControl.prototype.initialize = function(map)
  {
    return map.getContainer().appendChild(this.element);
  }
  FLD.BlockControl.prototype.getDefaultPosition = function()
  {
    return new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(7,7));
  }

} // end if(Google)

