/* setting global variables here */

var TEMP_COUNTRIES = null; // stores countries with temp data
var PRECIP_COUNTRIES = null; // stores countries with precip data
var SNOW_COUNTRIES = null; // stores countries with snow data
var HOURLY_PRECIP_COUNTRIES = null; // stores countries with hourly precip data

// hash of stations => data for each measurement
var PRECIP_STATIONS = new Array();
var TEMP_STATIONS = new Array();
var SNOW_STATIONS = new Array();
var HOURLY_PRECIP_STATIONS = new Array();

/* used in conjunction with stations bitmask */
var MEAS_BITMASK = {
  TEMP   : 1,
  PRECIP : 2,
  SNOW   : 4,
  HOURLY_PRECIP : 8
};


function getParams(url, params) {
  var ps = url.split('?');

  if (ps[1])
  {
    var pairs = ps[1].split('&');

    for (var i = 0; i < pairs.length; i ++)
    {
      var pair = pairs[i].split('=');

      if (pair.length == 2)
      {
        params[unescape(pair[0])] = unescape(pair[1]).replace(/[^a-zA-Z0-9\-.\/ ]/g, '');
      }
    }
  }

  return params;
}

function initializeQuote(i) {
  var q = quotes[i];

  if ((typeof q) == 'string')
  {
    q = eval(q);
    quotes[i] = q;
  }

  return q;
}

function initializeFromContract(id, contract) {
  for (var i = 0; i < CONTRACTS.length; i ++)
  {
    var target = CONTRACTS[i][0];

    if (target == id)
    {
      document.getElementById('contractType').value = target;
      document.getElementById('contractType').onchange();
      initializeQuote(i);
      quotes[i].initializeFromContract(contract);
    }
  }
}

function makeActive(target, doesHideAlert)
{
  // if the type of contract is dutch frost contract, then redirect
  // the page to /quote/nlfrost
  if (target == 'DutchFrostContract') {
    // TODO (Jinal) add a function name geContextPath in _jsincludes.ftl
    // and concatenate /quote/dutch to that to avoid problems
    // with a wfe deployed on a non started path where /quote/dutch won't work.
    window.location = "/quote/nlfrost";
  } else {
    for (var i = 0; i < CONTRACTS.length; i ++)
    {
      var id = CONTRACTS[i][0];
      var div = document.getElementById(id);

      if (i == target)
      {
        target = id;
      }

      if (id == target)
      {
        initializeQuote(i);
        div.style.display = 'block';
      }
      else
      {
        div.style.display = 'none';
      }
    }

    STATE.active = target;

    if (doesHideAlert)
    {
      document.getElementById('Common_div_alert').style.display = 'none';
    }

    saveState();
  }
}

function onTypeChanged() {
  makeActive(this.value, true);
}

var map = null;
var mapPopup = null;
var calendarPopup = null;
var helpPopup = null;
var quotes = null;
var getPriceURL = null;
var buyNowURL = null;
var UNITS = null;
var isDebug = false;

function PopupWindow_attachListener() {
  if (document.layers)
  {
    document.captureEvents(Event.MOUSEDOWN);
  }

  window.popupWindowOldEventListener = document.onmousedown;

  if (window.popupWindowOldEventListener != null)
  {
    document.onmousedown = new Function("window.popupWindowOldEventListener();PopupWindow_hidePopupWindows();");
  }
  else
  {
    document.onmousedown = PopupWindow_hidePopupWindows;
  }
}

/* custom hidePopup function for calendars */

function PopupWindow_hidePopup() {
  if (this.divName != null)
  {
    if (this.use_gebi)
    {
      document.getElementById(this.divName).style.visibility = "hidden";
    }
    else if (this.use_css)
    {
      document.all[this.divName].style.visibility = "hidden";
    }
    else if (this.use_layers)
    {
      document.layers[this.divName].visibility = "hidden";
    }
  }
  else
  {
    if (this.popupWindow && !this.popupWindow.closed)
    {
      this.popupWindow.close();
      this.popupWindow = null;
    }
  }
}

/* select a currency */
function currencyselect(currency_formelt, defaultCurrency) {
  document.write('<select id="' + currency_formelt +
                 '" name="currency" onChange="currencyChanged(' + "'" +
                 currency_formelt + "'" + ')">');
  var currencies = [["CAD", "Canadian Dollars"], ["EUR", "Euros"],
                    ["GBP", "British Pounds"],["USD", "US Dollars"]];

  for (var i = 0; i < currencies.length; i++) {
    var curr = currencies[i];
    var selectedStr = '';
    if (curr[0] == defaultCurrency) {
      selectedStr = 'selected';
    }
    document.write('<option ' + selectedStr + ' value="' + curr[0] + '">' +
                   curr[0] + '</option>');
  }
  document.write('</select>');
}

/* select a country */
function countryselect(country, defaultCountry) {
  var countries = null;
  document.write('<select id="' + country +
                 '" name="country" onChange="countryChanged(' + "'" +
                 country + "'" + ')">');
 /* Only 23 stations available for snowfall */
  if (country == 'SnowDay_select_country' ||
      country == 'SnowSeason_select_country' ||
      country == 'SnowSeasonBinary_select_country' ) {
    countries = getSnowCountries();
  } else if (country == 'RainySeason_select_country' ||
      country == 'RainySeasonBinary_select_country' ||
      country == 'DrySeason_select_country' ||
      country == 'DrySeasonBinary_select_country' ||
      country == 'DryDay_select_country' ||
      country == 'RainyDay_select_country') {
    countries = getPrecipCountries();
  } else if (country == 'RainyEventBinary_select_country') {
      countries = getHourlyPrecipCountries();
  } else {
    countries = getTempCountries();
  }

  for (var i = 0; i < countries.length; i++) {
    var cnt = countries[i];
    if (cnt[0] == defaultCountry) {
      document.write('<option value="' + cnt[0] + '" selected>' +
                     cnt[1] + '</option>');
    }
    else {
      document.write('<option value="' + cnt[0] + '">' + cnt[1] + '</option>');
    }
  }
  document.write('</select>');
}

/* select a station. this will be empty when no country is selected */
function stationselect(id, country, elName) {
  elName = elName || "rmsid";
  var stations = null;
  document.write('<select id="' + id + '" name="' + elName + '" onChange=' +
                 '"stationChanged(' + "'" + id + "'" + ')">' +
                 '<option value="">Select your nearest weather station...' +
                 '</option>');

  /* Only 23 stations available for snowfall */
  if (id == 'SnowDay_select_rmsid' || id == 'SnowSeason_select_rmsid' ||
      id == 'SnowSeasonBinary_select_rmsid' ) {
    stations = getSnowStations(country);
  } else if (id == 'RainySeason_select_rmsid' ||
    id == 'RainySeasonBinary_select_rmsid' ||
    id == 'DrySeason_select_rmsid' ||
    id == 'DrySeasonBinary_select_rmsid' ||
    id == 'DryDay_select_rmsid' ||
    id == 'RainyDay_select_rmsid') {
    stations = getPrecipStations(country);
  } else if (id == 'RainyEventBinary_select_rmsid') {
    stations = getHourlyPrecipStations(country);
  } else {
    stations = getTempStations(country);
  }


  for (var i = 0; i < stations.length; i ++) {
    var station   = stations[i];
    if (station[7] == country) {
      document.write('<option value="' + station[1] + '">' + station[3] +
                     ' - ' + station[6] + '</option>');
    }
  }
  document.write('</select>');
}

/* required functions for calendar */

var DATEFORMAT = 'mm/dd/yy';

function LZ(x) {
  return ((x < 0 || x > 9) ? "" : "0") + x;
}

function ZL(x) {
  return parseInt(x.replace(/^0+/, ''));
}

function getDateFromFormat(val, format) {
  return parseDate(val).getTime();
}

function parseDate(string) {
  var fields = string.split('/');
  var formatFields = DATEFORMAT.split('/');

  var yearField = '';
  var monthField = '';
  var dateField = '';

  for (var i = 0; i < formatFields.length; i ++)
  {
    if (formatFields[i] == 'yy')
    {
      yearField = fields[i];
    }
    else if (formatFields[i] == 'mm')
    {
      monthField = fields[i];
    }
    else if (formatFields[i] == 'dd')
    {
      dateField = fields[i];
    }
  }

  var year = ZL(yearField);

  if (year < 100)
  {
    if (year >= 70)
    {
      year = year + 1900;
    }
    else
    {
      year = year + 2000;
    }
  }

  return new Date(year, ZL(monthField) - 1, ZL(dateField));
}

function formatDate0(y, m, d) {
  var formatFields = DATEFORMAT.split('/');
  var fields = ['','',''];

  for (var i = 0; i < formatFields.length; i ++)
  {
    if (formatFields[i] == 'yy')
    {
      fields[i] = y;
    }
    else if (formatFields[i] == 'mm')
    {
      fields[i] = m;
    }
    else if (formatFields[i] == 'dd')
    {
      fields[i] = d;
    }
  }

  return LZ(fields[0]) + '/' + LZ(fields[1]) + '/' + LZ(fields[2]);
}

function formatDate(date) {
  var year = date.getFullYear();

  if (year >= 2000)
  {
    year = year - 2000;
  }
  else
  {
    year = year - 1900;
  }

  return formatDate0(year, date.getMonth() + 1, date.getDate());
}

/* end required functions for Celendar */

var monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
                  "Oct", "Nov", "Dec"];

function getMonthName(date)
{
  return monthNames[date.getMonth()];
}

function calendarPopupReturn(y, m, d)
{
  calendarPopup.source.value = formatDate0(y, m, d);
  calendarPopup.source.onchange();
}

function init(getPrice, buyNow, maxCap, startDateShift, currency)
{
  mapPopup = new PopupWindow("mapFrame");
  mapPopup.autoHide();
  calendarPopup = new CalendarPopup("calendarFrame");
  calendarPopup.setTodayText('');
  calendarPopup.setReturnFunction("calendarPopupReturn");
  helpPopup = new PopupWindow("helpFrame");
  helpPopup.autoHide();
  getPriceURL = getPrice;
  buyNowURL = buyNow;
  curr = currency;
  hourlyStartDateShift = 4;
  hourlyMaxCap = 100000;

  /* required when the calendar is popped up and user decides to change the
  contract-type to avoid overlap of cal and the drop down menu */
  document.getElementById('contractType').onfocus =
                    function() {calendarPopup.hidePopup()};

  quotes = new Array(CONTRACTS.length);

  for (var i = 0; i < CONTRACTS.length; i ++)
  {
    var id = CONTRACTS[i][0];
    if(id == "RainyEventBinary") {
      quotes[i] = '(new ' + id + 'Quote({"pageState":STATE, "quote":new Quote(' +
                hourlyMaxCap + ',' + hourlyStartDateShift +
                '), "calendarPopup":calendarPopup, "mapPopup":mapPopup, ' +
                '"getPriceURL":getPriceURL, "buyNowURL":buyNowURL, ' +
                '"units":UNITS, "currency":curr, "isDebug":isDebug})).init()';
    }
    else {
     quotes[i] = '(new ' + id + 'Quote({"pageState":STATE, "quote":new Quote(' +
                maxCap + ',' + startDateShift +
                '), "calendarPopup":calendarPopup, "mapPopup":mapPopup, ' +
                '"getPriceURL":getPriceURL, "buyNowURL":buyNowURL, ' +
                '"units":UNITS, "currency":curr, "isDebug":isDebug})).init()';
    }
  }
}

/* TODO this isn't a good way of adding stations.
Ideally should send the countryname to addStations function
via add GEvent.addListener but that doesnt seem to work so putting this
HACK*/
function addStations(stations) {
  var bounds = map.getBounds();
  var lngExt = 1;
  var latExt = 1;
  var southWest = bounds.getSouthWest();
  var northEast = bounds.getNorthEast();

  var lngMin = southWest.lng() - lngExt;
  var lngMax = northEast.lng() + lngExt;
  var latMin = southWest.lat() - latExt;
  var latMax = northEast.lat() + lngExt;
  var isStationMarked = map['__isStationMarked__'];

  for (var i = 0; i < stations.length; i ++) {
    if (!isStationMarked[i]){
      var station = stations[i];
      var latStation = station[4];
      var lngStation = station[5];
      if ((lngStation >= lngMin) && (lngStation <= lngMax) &&
       (latStation >= latMin) && (latStation <= latMax)){
        var point = new GLatLng(latStation, lngStation);
        var marker = new GMarker(point, {'title': station[0] + ', ' +
                                          station[2] + ' ' + station[3]});
        marker['__station__'] = station;
        map.addOverlay(marker);
        isStationMarked[i] = true;
      }

    }
  }
}

/* check if its an hourly precip contract type */
function isHourlyPrecipContract() {
  if(document.getElementById("contractType").value == 'RainyEventBinary') {
    return true;
  }
  return false;
}

/* check if its a precip contract type */
function isPrecipContract() {
   // check for contractType!=null in cases like dutchpricing where
   // there is no element named contractType
   if (document.getElementById("contractType") != null &&
       (document.getElementById("contractType").value == 'RainySeason' ||
        document.getElementById("contractType").value == 'RainySeasonBinary' ||
        document.getElementById("contractType").value == 'DryDay' ||
        document.getElementById("contractType").value == 'RainyDay'))  {
    return true;
  }
  return false;
}

/* check if its a snow contract type */
function isSnowContract() {

  // check for contractType!=null in cases like dutchpricing where
  // there is no element named contractType
  if (document.getElementById("contractType") != null &&
      (document.getElementById("contractType").value == 'SnowDay' ||
       document.getElementById("contractType").value == 'SnowSeason' ||
       document.getElementById("contractType").value == 'SnowSeasonBinary')) {
    return true;
  }
  return false;
}

function getStations(country) {
  var stations = null;

  if (isSnowContract()) { // check if its a snow contract
    stations = getSnowStations(country);
  } else if (isPrecipContract()) { // check if its a precip contract
    stations = getPrecipStations(country);
  } else if (isHourlyPrecipContract()) {
    stations = getHourlyPrecipStations(country);
  } else { // else its a temperature contract
    stations = getTempStations(country);
  }
  return stations;
}

function addUSStations() {
  addStations(getStations("US"));
}
function addCanadaStations() {
  addStations(getStations("CA"));
}

function addDutchStations() {
  addStations(getStations("NL"));
}

function addUKStations() {
  addStations(getStations("UK"));
}

function addGermanyStations() {
  addStations(getStations("DE"));
}
function addSpainStations() {
  addStations(getStations("ES"));
}
function addNorwayStations() {
  addStations(getStations("NO"));
}

/*
 * Loads the google maps for a given country. Note that it used a function
 * named getStations which gets the correct stations for a selected contract
 * type
 * @param country
 *
 */
function loadGmap(country) {
  if (GBrowserIsCompatible()) {
    map = new GMap2(document.getElementById("mapBox"));
    map.setCenter(new GLatLng(37.4419, -122.1419), 13);
    map.addControl(new GSmallMapControl());
    var stations = getStations(country);
    map['__isStationMarked__'] = new Array(stations.length);


    for (var i = 0; i < stations.length; i ++)
    {
      map['__isStationMarked__'][i] = false;
    }

    GEvent.addListener(
      map,
      "click",
      function(marker, point) {
        if (marker) {
          var station = marker['__station__'];
          map['__station__'] = station;
          var stationInfo = '<div style="text-align:center">' +
                            '<br />' + station[0] + '<br />' +
                            station[2] + ' ' + station[3] + '<br />' +
                            '<a href="#" id="wbgmapanchor" onclick="return stationMarkerClicked()">Select This Station &raquo;</a></div>';
          marker.openInfoWindowHtml(stationInfo);
        }
      });

    /* TODO this will be changed so that addStations can take country as a
     parameter */
    if (country == "US") {
      GEvent.addListener(map,"moveend",
                         function() { addUSStations()});
      GEvent.addListener(map, "zoomend",
                         function() { addUSStations()});
    } else if (country == "CA") {
      GEvent.addListener(map,"moveend",
                         function() {addCanadaStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addCanadaStations()});
    } else if (country == "NL") {
      GEvent.addListener(map,"moveend",
                         function() {addDutchStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addDutchStations()});
    } else if (country == "UK") {
      GEvent.addListener(map,"moveend",
                         function() {addUKStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addUKStations()});
    } else if (country == "ES") {
      GEvent.addListener(map,"moveend",
                         function() {addSpainStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addSpainStations()});
    } else if (country == "NO") {
      GEvent.addListener(map,"moveend",
                         function() {addNorwayStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addNorwayStations()});
    } else if (country == "DE") {
      GEvent.addListener(map,"moveend",
                         function() {addGermanyStations()});
      GEvent.addListener(map, "zoomend",
                         function() {addGermanyStations()});

    }

    new GKeyboardHandler(map);
  }
}

function stationMarkerClicked()
{
  var station = map['__station__'];
  map.closeInfoWindow();
  mapPopup.hidePopup();
  map.target.station = station;
  map.target.value = station[1];
  map.target.onchange();
  return false;
}

function load(getPriceURL, buyNowURL, maxCap, startDateShift, currency) {
  var params = getParams(document.location.href, {});

  if (params.debug == 'true')
  {
    isDebug = true;
  }


  loadState();
  init(getPriceURL, buyNowURL, maxCap, startDateShift, currency);
  var isInit = STATE.init;
  STATE.init = false;
  makeActive(STATE.active, false);

  if ((typeof params.type) != 'undefined')
  {
    if (isInit)
    {
      initializeFromContract(params.type, params);
    }
  }

  return isInit;
}

function unload()
{
  GUnload();
  saveState();
}

/* state management */

var STATENODE = null;
var STATE = null;

/* loads current saved state in STATENODE (id = 'PAGESTATE') to STATE */

function loadState()
{
  STATENODE = document.getElementById('PAGESTATE');
  STATE = eval('(' + STATENODE.value + ')');
}

/* serializes state as JSON */

function serialize(object)
{
  var serialized = object;

  switch (typeof object)
  {
    case 'object':
    {
      var map = object;
      serialized = '{';
      var separator = '';
      for (var key in map)
      {
        serialized += separator + '\'' + key + '\':' + serialize(map[key]);
        separator = ',';
      }
      serialized += '}';
    }
    break;

    case 'string':
    {
      serialized = '\'' + serialized.replace(/'/g, '\\\'') + '\'';
    }
    break;
  }

  return serialized;
}

/* saves serialized STATE in STATENODE for restoration */

function saveState()
{
  STATENODE.value = serialize(STATE);
  /* window.location.hash = escape(STATENODE.value); */
}

/* get an object property with default value (default is {})*/

function getProperty(object, property, defaultValue)
{
  var currentValue = object[property];

  if (currentValue == undefined)
  {
    if (defaultValue == undefined)
    {
      defaultValue = {};
    }
    object[property] = defaultValue;
    currentValue = defaultValue;
  }

  return currentValue;
}

/**
 * Returns all stations in a country that support the provided measurement.
 * Results are not cached. Use cached functions below when possible.
 */
function getStationsForMeas(country, measurementBitMask) {
  stationList = new Array();
  var count = 0;
  bitmask = MEAS_BITMASK[measurementBitMask];
  // look at bit mask for this station to see if it supports this measurement.
  for (var i=0 ; i < STATIONS.length; i++) {
    var st = STATIONS[i];
    if (st[7] == country && (st[8] & bitmask) == bitmask) {
     stationList[count] = st;
     count++;
    }
  }
  return stationList;
}

/* Returns precip stations (cached) */
function getPrecipStations(country) {
  if (PRECIP_STATIONS[country] == null) {
    PRECIP_STATIONS[country] = getStationsForMeas(country, "PRECIP");
  }
  return PRECIP_STATIONS[country];
}

/* Returns precip stations (cached) */
function getTempStations(country) {
  if (TEMP_STATIONS[country] == null) {
    TEMP_STATIONS[country] = getStationsForMeas(country, "TEMP")
  }
  return TEMP_STATIONS[country];
}

/* Returns snow stations (cached) */
function getSnowStations(country) {
  if (SNOW_STATIONS[country] == null) {
    SNOW_STATIONS[country] = getStationsForMeas(country, "SNOW")
  }
  return SNOW_STATIONS[country];
}

function getHourlyPrecipStations(country) {
  if (HOURLY_PRECIP_STATIONS[country] == null) {
    HOURLY_PRECIP_STATIONS[country] =
        getStationsForMeas(country, "HOURLY_PRECIP");
  }
  return HOURLY_PRECIP_STATIONS[country];
}

/**
 * Retrieves a list of countries that support
 */
function getCountriesForMeas(measurement) {
  countries = new Array();
  var count = 0;
  var bitmask = MEAS_BITMASK[measurement];
  /* look at bit mask for this country to see if it contains stations for
     this measurement.  */
  for (var i=0 ; i < COUNTRIES.length; i++) {
    var cnt = COUNTRIES[i];
    if ((cnt[2] & bitmask) == bitmask) {
      countries[count] = cnt;
      count++;
    }
  }
  return countries;
}

/* Returns temp countries */
function getTempCountries() {
  if (TEMP_COUNTRIES == null) {
    TEMP_COUNTRIES = getCountriesForMeas("TEMP");
  }
  return TEMP_COUNTRIES;
}

/* Returns precip countries */
function getPrecipCountries() {
  if (PRECIP_COUNTRIES == null) {
    PRECIP_COUNTRIES = getCountriesForMeas("PRECIP");
  }
  return PRECIP_COUNTRIES;
}

/* Returns hourly precip countries */
function getHourlyPrecipCountries() {
  if (HOURLY_PRECIP_COUNTRIES == null) {
    HOURLY_PRECIP_COUNTRIES = getCountriesForMeas("HOURLY_PRECIP");
  }
  return HOURLY_PRECIP_COUNTRIES;
}

/* Returns snow countries */
function getSnowCountries() {
  if (SNOW_COUNTRIES == null) {
    SNOW_COUNTRIES = getCountriesForMeas("SNOW");
  }
  return SNOW_COUNTRIES;
}
