/*
Copyright 2009 Google Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

var total;
var countryNameForCode;

var startYear = '1990';
var finalYear = '2009';
//var growthTarget = -5.2;
var growthTarget = 0;
var LULUCFMid = 0;
var gigagramsCarbon = 'Gg CO<sub>2</sub> eq.';
var prefixDots = '......';
var hideTooltipOnClick = true;

function stripSubheader(str) {
  while (str.startsWith(prefixDots)) {
    str = str.replace(prefixDots, '');
  }
  return str;
}

var dstColorDict;
var gradientList;
var gradientConfigName;
var gradientConfig;
var rendererData;

var legendDict = {};
var currentView = {
  'sector': '',
  'year': '',
  'gas': '',
  'countryCode': '',
  'sortOrder': 'numericValue',
  'reverseSort': false
};

var tooltipHtmlForId = {
  'interface_help': 'This page provides access to greenhouse gas (GHG) data for Annex I Parties containing information on anthropogenic GHG emissions/removals for the period from the base year to the latest available year.<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#interface_help">More...</a>',
  'sector_help': 'GHG emissions/removals estimates are presented in accordance with the categories (sectors, sub-sectors or more detailed categories) as defined in the IPCC Guidelines for National GHG Inventories (1996).<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#sector_help">More...</a>',
  'gas_help': 'The national anthropogenic GHG emissions/removals are presented for carbon dioxide (CO2), methane (CH4), nitrous oxide (N2O), hydrofluorocarbons (HFCs), perfluorocarbons (PFCs), sulphur hexafluoride (SF6) and the "aggregate GHGs".<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#gas_help">More...</a>',
  'year_help': 'GHG data are available for the base year and all years from 1990 to the latest available year; also available are changes from the base year to the latest available year, and changes over the period 1990 to the latest available year.<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#year_help">More...</a>',
  'legend_help': 'Color gradients ranging from light purple to blue indicate absolute emissions or positive growth.<br>Color gradients ranging from light to dark green indicate carbon sinks or negative growth.<br>Color gradients of yellow indicate growth rate close to 0%.<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#legend_help">More...</a>',
  'EUC_help': 'European Union (15) refers to the 15 member States that were members of the European Union prior to May 2004.<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#EUC_help">More...</a>',
  'EU-27_help': 'European Union (27) refers to the 27 member States of the European Union.<br><a href="http://unfccc.int/ghg_data/online_help/data_interface_help/items/4873.php#EU-27_help">More...</a>'
   };

function tooltipHtml(id) {
  var result = '&nbsp;<img src="questionMarkMap.png"';
  result += ('alt= "?" id="' + id + '_help" class="tooltip_needed"/>');
  return result;
}

var sectorTuples = [
  {code: 'to', name: 'Total emissions including LULUCF/LUCF'},
  {code: 'sans_lu', name: 'Total emissions excluding LULUCF/LUCF'},
  {code: 'en', name: 'Energy'},
  {code: 'en.fc', name: prefixDots + 'Fuel Combustion'},
  {code: 'en.fc.in', name: prefixDots + prefixDots + 'Energy Industries'},
  {code: 'en.fc.ma', name: prefixDots + prefixDots +
      'Manuf Industries and Construction'},
  {code: 'en.fc.tr', name: prefixDots + prefixDots + 'Transport'},
  {code: 'en.fc.os', name: prefixDots + prefixDots + 'Other Sectors'},
  {code: 'en.fc.on', name: prefixDots + prefixDots +
      'Other (Not elsewhere specified)'},
  {code: 'en.fu', name: prefixDots + 'Fuel Fugitive Emissions'},
  {code: 'in', name: 'Industrial Processes'},
  {code: 'so', name: 'Solvent and Other Product Use'},
  {code: 'ag', name: 'Agriculture'},
  {code: 'lu', name: 'LULUCF'},
  {code: 'wa', name: 'Waste'},
  {code: 'bu', name: 'International bunkers'},
  {code: 'bu.av', name: prefixDots + 'Aviation'},
  {code: 'bu.ma', name: prefixDots + 'Marine'}
];

var totalwithLUCode = 'to';
var totalSansLUCode = 'sans_lu';

function codeMeansTotal(sectorCode) {
  return (sectorCode == totalwithLUCode || sectorCode == totalSansLUCode);
}

function showSectorCodeOnTotalsChart(sectorCode) {
  // Do now show totals
  if (codeMeansTotal(sectorCode)) {
    return false;
  }
  // Do not show bunkers
  if (sectorCode.startsWith('bu')) {
    return false;
  }

  // Do not show subsectors
  if (sectorCode.indexOf('.') > 0) {
    return false;
  }

  // Show everything else - just the top-level sectors.
  return true;
}

function showSectorCodeOnEnergyChart(sectorCode) {
  // Show only energy subcategories
  if (sectorCode.startsWith('en.') && sectorCode != 'en.fc') {
    return true;
  }

  // Ignore everything else.
  return false;
}

function getFlashMovie() {
  var isIE = navigator.appName.indexOf('Microsoft') != -1;
  var movieName = (isIE ? 'flash_object' : 'flash_embed');
  return document.getElementById(movieName);
}

function getSectorName(sectorCode) {
  var result = '';
  for (var i = 0; i < sectorTuples.length; i++) {
    sectorTuple = sectorTuples[i];
    if (sectorTuple['code'] == sectorCode) {
      return sectorTuple['name'];
    }
  }
  return 'Unknown sector for code ' + sectorCode;
}

function showingGrowth() {
  return currentView.year.startsWith('growth');
}

function showingLULUCF() {
  return currentView.sectorCode.startsWith('lu') &&
    (currentView.gas == 'CO2' || currentView.gas.startsWith('Aggregate')
  );
}
function saveSettings() {
  currentView.year = $('#year').val();
  currentView.sectorCode = $('#sector').val();
  currentView.gas = $('#gas').val();
}

function init(aGradientConfigName) {
  gradientConfigName = aGradientConfigName;
  initDetailsDiv();
  $(window).click(function() {
    if (hideTooltipOnClick) {
      $('#tooltip_parent').hide();
    }
  });
  $('#tooltip').click(function(event) {
    event.stopPropagation();
  });
  $('#print_map').click(function()
  {
    showPrintMapPopup();
    return false;
  });

  growth_option1 = (
      '<option value="growth_base_final" selected> Base Year-2009 growth, % </option>');
  $(growth_option1).appendTo($('#year'));
  growth_option2 = (
      '<option value="growth_1990_final"> 1990-2009 growth, % ' +
      '</option>');
  $(growth_option2).appendTo($('#year'));

  for (var year = 2009; year >= 1990; year--) {
    var option = '<option value="' + year + '">' + year + '</option>';
    $(option).appendTo($('#year'));
  }
  $('<option value="base"> Base Year </option>').appendTo($('#year'));

  var urlYear = urlParam('year');
  var urlSector = urlParam('sector');
  var urlGas = urlParam('gas');
  if (urlYear && urlSector && urlGas) {
    $('#year').val(urlYear);
    $('#sector').val(urlSector);
    $('#gas').val(urlGas);
  }

  saveSettings();
  $.getJSON('countryNameForCode.js', countryCodeDone);
  $.getJSON(gradientConfigName, gradientConfigDone);
}

function setTooltip(event, html) {
  $('#tooltip_parent').css(
      'left', (event.pageX - $('#tooltip_parent').width() / 2) + 'px');
  $('#tooltip_parent').css('top', (event.pageY + 10) + 'px');

  $('#tooltip').html(html);
  $('#tooltip_parent').show();

  event.stopPropagation();
}

function setTooltipHandler() {
  $('.tooltip_needed').die('click');
  $('.tooltip_needed').live('click', function(event) {
    html = tooltipHtmlForId[$(this).attr('id')];
    hideTooltipOnClick = true;
    setTooltip(event, html);
    return false;
 });
  $('.link_action_element').live('click', function(event) {
    var html = (
        'Paste link in <strong>email</strong> or <strong>IM</strong>' +
        '<br><input id="link_text" type="text" style="width:100%" value="' +
        linkUrl() + '"></input>');
    hideTooltipOnClick = false;
    setTooltip(event, html);
    $('#link_text').select();
    return false;
  });
}


function initDetailsDiv() {
  $('#flash_container').css('z-index', 2);
  $('#details_layer').hide();

  $('#print').click(function()
  {
    hideDetails();
    showDetailsPopup(true);
    // Use setTimeout() to work around Chrome/Safari "feature"
    // that does not render HTML until something happens in the print dialog.
    setTimeout(function() {
      detailsWindow.print();
    }, 100);
    return false;
  });

  $('#close').click(function()
  {
    hideDetails();
    return false;
  });

  $('#close_tooltip').click(function()
  {
    $('#tooltip_parent').hide();
    return false;
  });
}

function hideDetails() {
  $('#details_layer').hide();
  detailsWindow = undefined;
}

function getEmissionsForYearGas(year, gas) {
  gas = gas || currentView.gas;
  year = year || currentView.year;
  return parseJSON(getFlashMovie().getEmissionsForYearGas(year, gas));
}

function getEmissionsForYearGasSector(year, gas, sectorCode) {
  gas = gas || currentView.gas;
  year = year || currentView.year;
  sectorCode = sectorCode || currentView.sectorCode;
  var gasDict = getEmissionsForYearGas(year, gas);
  if (sectorCode in gasDict) {
    return gasDict[sectorCode];
  } else {
    return undefined;
  }
}

function calcDetails() {
  var tableTuples = [];
  gasDict = getEmissionsForYearGas();
  var countryCode = currentView.countryCode
  for (var i = 0; i < sectorTuples.length; i++) {
    var sectorTuple = sectorTuples[i];
    var sectorCode = sectorTuple.code;
    if (sectorCode in gasDict && countryCode in gasDict[sectorCode]) {
      var value = gasDict[sectorCode][countryCode];
      tableTuples.push({
          'code': sectorCode,
          'name': sectorTuple['name'],
          'value': value
      });
    }
  }
  return tableTuples;
}

function tableCellWithHtml(html, cellType) {
  var cell = $('<' + cellType + '></' + cellType + '>').attr('align', 'center');
  var div = $('<div></div>');
  cell.append(div);
  div.html(html);
  return cell;
}

function headerCellWithHtml(html) {
  return tableCellWithHtml(html, 'th');
}

function normalCellWithHtml(html) {
  return tableCellWithHtml(html, 'td');
}

// Internet Explorer does not allow jQuery DOM chaining of type
// td.attr(a).css(b).append_to(c);
function getDetailsHtml(tableTuples, countryCode, units) {
  if (! tableTuples) {
    return '<p>No data';
  }

  var details = $('#details');
  var countryName = countryNameForCode[countryCode];

  var year = currentView.year;

  var outerTable = $('<table></table>').css('border-spacing', '1px').css(
      'margin-top', '-20px');

  var link;
  if (currentView.countryCode == 'EU-27') {
    link = 'http://unfccc.int/files/ghg_data/ghg_data_unfccc/ghg_profiles/';
    link += 'application/pdf/eu-27_ghg_profile.pdf';
  } else {
    link = 'http://unfccc.int/files/ghg_emissions_data/application/pdf/';
    if (currentView.countryCode == 'ROM') {
       link += 'rou';    
    } else {
       link += countryCode.toLowerCase();
    }
    link += '_ghg_profile.pdf';
  }


  titleHtml = (
      '<span class="header" style="color: #666">Details for ' + countryName);
  titleHtml += '</span>&nbsp;&nbsp;<a target=_blank href="' + link;
  titleHtml += '" style="font-size: 13px; font-weight: normal">'
  titleHtml += 'Full report</a><br>';
  outerTable.append($('<tr></tr>').append(
      normalCellWithHtml(titleHtml).attr('colspan', 2).attr('align', 'left')));

  var signatureDiv = $('<div></div>').addClass('normal').css(
      'width', '730px').append(getSignature());
  var signatureTd = $('<td></td>').attr('colspan', 2).attr(
      'align', 'left').css('padding-bottom', '1em');
  signatureTd.append(signatureDiv);
  outerTable.append($('<tr></tr>').append(signatureTd));

  var innerTable = $('<table></table>').addClass('DetailsTable').css(
      'border-spacing', '0px').css('margin-top', '-0.3em');

  var totalsTuples = [];
  var energyTuples = [];

  var innerTr = $('<tr></tr>');
  innerTable.append(innerTr);

  var innerTd = $('<td></td>').attr('colspan', 2);
  innerTd.attr('align', 'left').attr('valign', 'top').css(
      'padding-bottom', '1em');
  innerTr.append(innerTd);

  var innerDiv = $('<div></div').css('padding-top', '0.1em').css(
      'width', '320px');
  innerDiv.append($('<span></span>').addClass('header').append(
      'Breakdown by sector&nbsp;'));
  if (showingGrowth()) {
    innerDiv.append($('<span></span>').addClass('normal').append(
        'Absolute change (relative change)'));
  }
  innerTd.append(innerDiv);

  for (var i = 0; i < tableTuples.length; i++) {
    var tableTuple = tableTuples[i];
    var sectorName = tableTuple.name;
    var sectorCode = tableTuple.code;
    var tr = $('<tr></tr>')
    var backgroundColor = 'ffffff';
    if (i % 2 == 0) {
      backgroundColor = 'eeeeee';
    }
    innerTable.append(tr);

    var value = tableTuple.value;
    var printableValue = getPrintableValueAndMaybeGrowth(value);
    var absValue = getAbsValue(value);
    var sectorTd = $('<td></td>');
    sectorTd.css('text-align', 'left').css('font-size', '0.8em');
    sectorTd.append(sectorName);
    sectorTd.appendTo(tr);
    var textTd = $('<td></td>');
    textTd.css('text-align', 'right').css('font-size', '0.8em');
    textTd.append(printableValue);
    textTd.appendTo(tr);

    var tuple = {'label': stripSubheader(sectorName), 'value': absValue};
    if (showingGrowth()) {
      tuple.growth = getMapValue(value);
    }

    if (showSectorCodeOnTotalsChart(sectorCode)) {
      totalsTuples.push(tuple);
    }
    if (showSectorCodeOnEnergyChart(sectorCode)) {
      energyTuples.push(tuple);
    }
  }

  var mainTr = $('<tr></tr>');
  outerTable.append(mainTr);

  var tableTd = $('<td></td>');
  tableTd.attr('valign', 'top').attr('align', 'right').attr('rowspan', 4);
  tableTd.append(innerTable);
  mainTr.append(tableTd);


  var titleCell1 = $('<td></td>')
  mainTr.prepend(titleCell1);

  var chartCell1 = $('<td></td>');
  var main2Tr = $('<tr></tr>');
  main2Tr.append(chartCell1);
  outerTable.append(main2Tr);

  var chartWidth = 767;
  titleCell1.attr('valign', 'top').attr('align', 'left').css(
      'padding-bottom', '15px');
  chartCell1.attr('valign', 'center').attr('align', 'left').css(
      'padding-bottom', '1em');

  var chartYear = year;
  if (chartYear == 'growth_base_final') {
    chartYear = 'growth_base_' + finalYear;
  } else if (chartYear == 'growth_' + startYear + '_final') {
    chartYear = 'growth_' + startYear + '_' + finalYear;
  }
  var chartUrlBase = (
    'charts/' + chartYear + '_' + currentView.gas +
      '_' + currentView.countryCode + '_').replace(' ', '_');
  var totalsChart = $('<img></img>').attr(
      'src', chartUrlBase + 'total.png').attr('width', 330).attr('height', 180);
  if (totalsChart) {
    titleCell1.append($('<span></span>').addClass('header').append(
        'Total emissions by sector'));
    chartCell1.append(totalsChart);
  }

  var main3Tr = $('<tr></tr>');
  var main4Tr = $('<tr></tr>');
  outerTable.append(main3Tr);
  outerTable.append(main4Tr);
  var titleCell2 = $('<td></td>');
  main3Tr.append(titleCell2);
  var chartCell2 = $('<td></td>');
  main4Tr.append(chartCell2);
  titleCell2.attr('valign', 'top').attr('align', 'left').css(
      'padding-bottom', '15px');
  chartCell2.attr('valign', 'center').attr('align', 'left');
  var energyChart = $('<img></img>').attr(
      'src', chartUrlBase + 'energy.png').attr('width', 330).attr(
          'height', 180);
  if (energyChart) {
    titleCell2.append($('<span></span>').addClass('header').append('Energy'));
    chartCell2.append(energyChart);
  }


  // No final year data for most countries, hence not showing growth.
  if (! showingGrowth()) {
    var pop = parseJSON(
        getFlashMovie().getDataForYearCountry(
            'population', year, countryCode));
    var gdp = parseJSON(
        getFlashMovie().getDataForYearCountry(
            'gdp', year, countryCode));
    var popElem = $('<td></td>').attr('align', 'left').css(
        'padding-top', '1em').css('font-size', '0.8em');
    if (pop && pop != 0) {
      popElem.append($('<span></span>').addClass('header').append(
          'Population'));
      popElem.append(', ' + yearString(year) + ': ' + numWithCommas(pop));
    }
    var gdpElem = $('<td></td>').attr('align', 'right').css(
        'padding-top', '1em').css('font-size', '0.8em');
    if (gdp && gdp != 0) {
      gdpElem.append($('<span></span>').addClass('header').append('GDP'));
      gdpElem.append(', ' + yearString(year) + ', constant 2000 USD: ');
      gdpElem.append(numWithCommas(gdp) + ' billion');
    }

    if (popElem || gdpElem) {
      outerTable.append($('<tr></tr>').append(popElem).append(gdpElem));
    }
  }

  /*outerTable.append($('<tr></tr>').append(
      normalCellWithHtml(
          '<input type="submit" onClick="javascript:hideDetails()"' +
      'value="Close" />').attr('colspan', 2)));*/
  var result = $('<div></div>');
  var center = $('<center></center>');
  center.append('<br>');
  center.append(outerTable);
  center.append('<br>');
  result.append(center);
  return result.html();
}

var detailsWindow;
var detailsHTML;
var detailsShowPrintDialog;

// Show floating divs on Windows and Macs. But on Linux
// floating divs can't be put above Flash elements, so we resort to popups.
function detailsAsPopup() {
  // Default to popup.
  if (navigator.platform == undefined) {
    return true;
  }
  var os = navigator.platform;

  // MSIE 6 shows combo boxes above floatin div.
  //if (typeof document.body.style.maxHeight === "undefined") {
  //  return true;
  //}
  return (os.indexOf('Win') == -1 && os.indexOf('Mac') == -1);
}

// Problems setting it dynamically, though
var detailsTitle = 'Details for';

function detailsWindowIsNotPopup() {
  return detailsWindow == undefined || detailsWindow == 'div';
}

function showDetailsPopup(showPrintDialog) {
  detailsShowPrintDialog = showPrintDialog;
  var detailsUrl = 'details.html';
  if (detailsWindowIsNotPopup()) {
    detailsWindow = window.open(
        detailsUrl, 'details',
        'height=550,width=830,toolbar=yes,menubar=yes,resizable=yes');
  } else {
    detailsWindow.initDetailsPage(detailsTitle);
  }
  if (!detailsWindow) {
    alert('Please enable popups to view the details page.');
    return;
  }
  if (window.focus) {
    detailsWindow.window.focus();
  }
}

function showDetailsInternal() {
  var offset = $('#flash_container').offset();
  $('#details_layer').css('top', offset.top);
  $('#details_layer').css('left', offset.left);

  $('#details_layer').width($('#flash_container').width() + 10);

  var totalHeight = $('#legend').offset().top + $('#legend').height() +
    15 - $('#flash_container').offset().top;
  $('#details_layer').height(totalHeight);
  detailsHTML = getDetailsHtml(
      calcDetails(), currentView.countryCode, getUnits());
  if (detailsAsPopup()) {
    showDetailsPopup(false);
  } else {
    if (detailsWindowIsNotPopup()) {
      $('#details_title').text(detailsTitle);
      $('#details').html(detailsHTML);
      $('#details_layer').show();

      // Assigning $('#details') here does not work in Chrome
      detailsWindow = 'div';
    } else {
      // The floating div was opened as a popup.
      showDetailsPopup(false);
    }
  }
}

function getPrintMapSettings() {
  var settings = {
    'map_row': $('#map_row').html(),
    'legend_row': $('#legend_row').html(),
    'table_header_row': (
        '<td>' + $('#left_country_list_header').html() + '</td>'),
    'table_row': $('#table_row').html(),
    'rendererDataString': JSON.stringify(rendererData)
  };
  // IE reads an Array as an Object between browser windows,
  // so we have to encode data as JSON beforehand.
  return settings;
}

function showPrintMapPopup() {
  var mapUrl = 'printMap.html';
  var printMapWindow = window.open(
        mapUrl, 'map',
        'height=1000,width=800,toolbar=yes,menubar=yes,resizable=yes');
  if (!printMapWindow) {
    alert('Please enable popups to view the details page.');
    return;
  }
  if (window.focus) {
    printMapWindow.window.focus();
  }
}


function parseJSON(str) {
  var dict;
  try {
    dict = JSON.parse(str);
  } catch (er) {
    alert('Error parsing JSON: ' + er);
  }
  return dict;
}

function countryCodeDone(json) {
  countryNameForCode = json;
}

function gradientConfigDone(json) {
  gradientConfig = json;
}

function printableLegendValue(name, aDict) {
  var numberFormat = '%.0f';
  if (showingGrowth()) {
    numberFormat = '%.2f';
  }
  var result = numWithCommas(sprintf(numberFormat, aDict[name]));
  if (showingGrowth()) {
    result += '%';
  }
  return result;
}

function setLegendValue(name, aDict) {
  $('#' + name).html(printableLegendValue(name, aDict));
}

function showLegend() {
  var legend = getUnits();
  legend += tooltipHtml('legend');
  $('#legend').html(legend);
}

function getUnits() {
  result = gigagramsCarbon;
  if (showingGrowth()) {
    result += ', change';
  }
  result += (', ' + yearString(currentView.year));
  return result;
}

function yearString(year) {
  if (showingGrowth()) {
    if (year == 'growth_' + startYear + '_final') {
      return startYear + ' to ' + finalYear;
    } else if (year == 'growth_base_final') {
      return 'Base Year to ' + finalYear;
    } else {
      return 'Unknown growth option ' + growthOptionName;
    }
  } else if (year == 'base') {
    return 'Base Year';
  } else {
    return year;
  }
}

function changeView() {
  if (!getFlashMovie()) {
    return;
  }

  if (!countryNameForCode) {
    setTimeout(changeView, 200);
    return;
  }

  var urlZoom = parseInt(urlParam('zoom'));
  var urlLat = parseFloat(urlParam('lat'));
  var urlLng = parseFloat(urlParam('lng'));
  if (urlZoom && urlLat && urlLng) {
    getFlashMovie().setViewPort(JSON.stringify({
      'zoom': urlZoom,
      'lat': urlLat,
      'lng': urlLng
    }));
  }

  saveSettings();
  getFlashMovie().clearMap();
  $('#details').empty();

  sectorData = [];
  var currentData = getEmissionsForYearGasSector();
  if (currentData != undefined) {
    for (var countryCode in countryNameForCode) {
      var value = currentData[countryCode];
      var mapValue;
      if (value) {
        mapValue = getMapValue(value);
      } else {
        mapValue = '0.00';
      }
      var floatValue = parseFloat(mapValue);
      if (!isNaN(floatValue)) {
        sectorData.push(floatValue);
      }
    }
  }

  // Need at least one value for min/max calculations.
  if (sectorData.length == 0) {
    sectorData = [NaN];
  }
  var dataMax = arrayMax(sectorData);
  var dataMin = arrayMin(sectorData);
  var dataMid;
  if (showingGrowth()) {
    dataMid = growthTarget;
  } else if (showingLULUCF()) {
    dataMid = LULUCFMid;
  } else {
    dataMid = (dataMin + dataMax) / 2;
  }

  legendDict = {'min': dataMin, 'mid': dataMid, 'max': dataMax};

  legendDict['unit'] = getUnits();
  changePolyStyle();
  showLegend();
  changeCountryList();
  $('#link').html('<a href="">Link</a>');

  if (detailsWindow) {
    showDetails();
  }
  // If new matching elements were generated, we have to re-find all of them.
  setTooltipHandler();
}

function linkHtml() {
  return '<a href="' + linkUrl() + '">Link</a>';
}

function linkUrl() {
  var urlList = window.location.href.split('?');
  var url = urlList[0];
  var result = url + '?year=' + currentView.year;
  result += ('&gas=' + currentView.gas + '&sector=' + currentView.sectorCode);
  if (typeof getFlashMovie().getViewPort == 'function') {
    var mapSettings = parseJSON(getFlashMovie().getViewPort());
    result += (
        '&zoom=' + mapSettings.zoom + '&lat=' + mapSettings.lat +
        '&lng=' + mapSettings.lng);
  }
  return result;
}

function changePolyStyle() {
  rendererData = {};
  rendererData.colors = calcColors();
  rendererData.infos = calcInfos();
  for (var k in {'min': 1, 'mid': 1, 'max': 1}) {
    legendDict['printable_' + k] = printableLegendValue(k, legendDict);
  }
  rendererData.gradientList = gradientList;
  rendererData.legendDict = legendDict;
  // The function may not have been loaded yet.
  if (typeof getFlashMovie().sendSelectionToFlash == 'function') {
    getFlashMovie().sendSelectionToFlash(JSON.stringify(rendererData));
  }

}

function getAbsValue(value) {
  if (showingGrowth()) {
    return value.delta;
  } else {
    return value;
  }
}

function getMapValue(value) {
  if (showingGrowth()) {
    return sprintf('%.2f', value.growth);
  } else {
    return value;
  }
}

function getPrintableValue(value) {
  if (null == value) {
    return '-';
  }

  var valueToCheck;
  if (typeof(value) == 'object') {
    valueToCheck = value.delta;
  } else {
    if (Math.abs(value) < 10) {
    	    valueToCheck = sprintf('%.2f', value);
    } else {
	    valueToCheck = value;
    }
  }
  if (
      (null == valueToCheck) || ('null' == valueToCheck) ||
      ('NaN' == valueToCheck) || isNaN(valueToCheck)) {
    return '-';
  } 
  return numWithCommas(valueToCheck);
}

function getPrintableValueAndMaybeGrowth(value) {
  if (showingGrowth()) {
    var deltaString = getPrintableValue(value.delta);
    if (deltaString == '-') {
      return deltaString;
    }
    return deltaString + ' (' + value.growth + '%)';
  } else {
    return getPrintableValue(value);
  }
}

function calcColors() {
  var gradientConfigChoice;
  if (showingGrowth()) {
    gradientConfigChoice = gradientConfig['growth'];
  } else if (showingLULUCF()) {
    gradientConfigChoice = gradientConfig['absolute_LULUCF'];
  } else {
    gradientConfigChoice = gradientConfig['absolute'];
  }
  gradientList = constructGradientList(
      gradientConfigChoice, legendDict['min'], legendDict['max']);

  var result = {};
  var dstPointCount = 10.0;

  var countryData = getEmissionsForYearGasSector();

  // Sector/gas combinations with no data should come out white.
  if (countryData == undefined) {
    for (var countryCode in countryNameForCode) {
      result[countryCode] = 'ffffff';
    }
    return result;
  }

  for (var countryCode in countryData) {
    var countryValue = countryData[countryCode];
    if (getPrintableValue(countryValue) == '-') {
      result[countryCode] = 'ffffff';
    } else {
      var value = parseFloat(getMapValue(countryValue));
      result[countryCode] = multiColorGradient(
          gradientList, value, dstPointCount);
    }
  }
  return result;
}

function constructGradientList(userGradientConfig, minValue, maxValue) {
  var result = [];
  for (var i = 0; i < userGradientConfig.length; i++) {
    var userEntry = userGradientConfig[i];
    var entry = {
      'maxPercent': userEntry.nextPercent
    };
    if (i == 0) {
      entry.minPercent = 0;
      entry.minValue = minValue;
    } else {
      entry.minPercent = result[i - 1].maxPercent;
      entry.minValue = result[i - 1].maxValue;
    }
    if ('nextValue' in userEntry) {
      entry.maxValue = userEntry.nextValue;
    } else {
      entry.maxValue = linearGradient(
        {'min': 0, 'max': 100},
        {'min': minValue, 'max': maxValue},
        entry.maxPercent
      );
    }
    if ('parts' in userEntry) {
      partResult = constructGradientList(
          userEntry.parts, entry.minValue, entry.maxValue);
      var startPercent = entry.minPercent;
      var percentRange = entry.maxPercent - entry.minPercent;
      for (var j = 0; j < partResult.length; j++) {
        partEntry = partResult[j];
        partEntry.minPercent = (
            startPercent + percentRange * partEntry.minPercent / 100);
        partEntry.maxPercent = (
            startPercent + percentRange * partEntry.maxPercent / 100);
      }
      result = result.concat(partResult);
    } else {
      entry.minColor = userEntry.minColor;
      entry.maxColor = userEntry.maxColor;
      result.push(entry);
    }
  }
  return result;
}

function translateGas(gas) {
  if (gas == 'CO2') {
    return 'CO<sub>2</sub>';
  }
  if (gas == 'CH4') {
    return 'CH<sub>4</sub>';
  }
  if (gas == 'N2O') {
    return 'N<sub>2</sub>O';
  }
  if (gas == 'SF6') {
    return 'SF<sub>6</sub>';
  }
  return gas;

}

function calcInfos() {
  result = {}
  var gasData = getEmissionsForYearGas();
  for (var countryCode in countryNameForCode) {
    var unit;
    if (showingGrowth()) {
      unit = '%';
    } else {
      unit = '' + gigagramsCarbon;
    }
    var str = '<center><b>' + countryNameForCode[countryCode];
    str += '      </b></center><br>\n';
    if (codeMeansTotal(currentView.sectorCode)) {
      var totalWithLU = numWithCommas(
          getMapValue(gasData[totalwithLUCode][countryCode]));
      var totalSansLU = numWithCommas(
          getMapValue(gasData[totalSansLUCode][countryCode]));
      str += 'Total with LULUCF: <b>' + totalWithLU;
      str += ('</b> ' + unit + '<br>\n');
      str += 'Total without LULUCF: <b>' + totalSansLU;
      str += ('</b>' + unit + '<br>\n');
    } else {
      str += stripSubheader(getSectorName(currentView.sectorCode));
      var gasValue;
      if (currentView.sectorCode in gasData) {
        gasValue = getPrintableValue(
            getMapValue(gasData[currentView.sectorCode][countryCode]));
      } else {
        gasValue = '0';
      }
      str += (': <b>' + gasValue + '</b> ' + unit);
    }
    result[countryCode] = str;
  }
  return result;
}

function debug(str) {
  //$('#details').html($('#details').html() + str + "<br>");
}

function getSignature() {
  return translateGas(currentView.gas) + ', ' + getUnits();
}

function changeCountryList() {
  var list = [];
  var layerData = getEmissionsForYearGasSector();
  var sectorCode = currentView.sectorCode;

  for (var countryCode in countryNameForCode) {
    var value;
    if (layerData != undefined) {
      value = getMapValue(layerData[countryCode]);
    } else {
      value = 0;
    }
    var listTuple = {
        'code': countryCode,
        'value': value,
        'name': countryNameForCode[countryCode]
    };
    if (typeof(value) == typeof('')) {
      try {
        listTuple.numericValue = parseFloat(value);
      } catch (er) {
        listTuple.numericValue = NaN;
      }
    } else {
      listTuple.numericValue = value;
    }
    list.push(listTuple);
  }

  if (list.length == 0) {
    return;
  }

  if (currentView.sortOrder == 'name') {
    list.sort(sortByField.curry(currentView.sortOrder));
  } else {
    list.sort(sortByNumericField.curry(currentView.sortOrder));
  }
  if (currentView.reverseSort) {
    list.reverse();
  }


  // It was hidden on startup to prevent from showing half-baked contents
  $('#right_country_list_header').show();

  var leftHeader = $('#left_country_list_header');
  leftHeader.empty();

  var span1 = $('<span></span>').addClass('header').css('float', 'left').css(
      'margin-bottom', '0px').css('padding', '0px').css(
          'border-width', '0').css('color', '#666');

  span1.append('All Annex I countries&nbsp;');

  var span2 = $('<span></span>').addClass('subheader');
  span2.append(' - ' + stripSubheader(getSectorName(sectorCode)));

  var span3 = $('<span></span>').addClass('minor');
  span3.append(getSignature());

  leftHeader.append(span1).append(span2).append('<br>').append(span3);

  $('#sort_name').empty();
  $('#sort_name').append(sortSpan('name'));
  $('#sort_value').empty();
  $('#sort_value').append(sortSpan('numericValue', 'value'));

  var table = $('<table></table>').attr('width', '780px').attr(
      'id', 'country_list_table');

  // The sane thing to do here would be to have three colspan=3
  // columns of fixed width, but it does not work in IE.

  var slices = [];
  slices[0] = countryListSlice(list, 0, 15, true);
  slices[1] = countryListSlice(list, 15, 30, false);
  slices[2] = countryListSlice(list, 30, 43, false);

  var numRows = Math.max(slices[0].length, slices[1].length, slices[2].length);

  for (var j = 0; j < numRows; j++) {
    var tr = $('<tr></tr>');
    tr.appendTo(table);
    for (var i = 0; i < slices.length; i++) {
      if (slices[i].length <= j) {
        tr.append($('<td></td>').attr('colspan', '3'));
        continue;
      }
      var slice = slices[i][j];
      for (var k = 0; k < slice.length; k++) {
        tr.append(slice[k]);
      }
    }
  }

  $('#country_list').empty();
  $('#country_list').append(table);
}

function resort(field) {
  if (field == currentView.sortOrder) {
    currentView.reverseSort = ! currentView.reverseSort;
  } else {
    currentView.sortOrder = field;
    if (field == 'name') {
      currentView.reverseSort = false;
    } else {
      currentView.reverseSort = true;
    }
  }
  changeCountryList();
}

function sortHeaderFilename(field) {
  if (field != currentView.sortOrder) {
    return 'no_sort.png';
  }
  if (currentView.reverseSort) {
    return 'reverse_sort.png';
  } else {
    return 'forward_sort.png';
  }
}

function sortSpan(field, visibleField) {
  if (! visibleField) {
    visibleField = field;
  }
  var sortSpan = $('<a></a>').attr('href', '').addClass('normal').click(
    function() {
      resort(field);
      return false;
  });
  sortSpan.css('color', '#cc0000');

  sortSpan.append('by ' + visibleField);
  if (currentView.sortOrder == field) {
    if (currentView.reverseSort) {
      sortSpan.append(' ascending');
    } else {
      sortSpan.append(' descending');
    }
  }
  return sortSpan;
}

function countryListSlice(list, startIndex, endIndex) {

  var slice = [];

  for (var i = startIndex; i < endIndex; i++) {
    var item = list[i];

    var code = item.code;
    var name = countryNameForCode[code];

    var td1 = $('<td></td>').css(
        'text-align', 'right').css('vertical-align', 'middle');
    td1.append($('<span></span>').css('font-weight', '900').append(i + 1));

    var td2 = $('<td></td>').css(
        'text-align', 'right').css('vertical-align', 'middle');
    printableValue = getPrintableValue(item.value);
    if (showingGrowth() && (printableValue != '-')) {
      printableValue += '%';
    }
    td2.append(printableValue);

    var td4 = $('<td></td>').css(
        'text-align', 'left').css(
            'vertical-align', 'middle').css(
                'padding-left', '0.4em').css('width', '10px');

    var td3 = $('<td></td>').css(
        'text-align', 'left').css(
            'vertical-align', 'middle').css(
                'padding-left', '0.4em').css('width', '160px');
    countryHTML = '<a href="" onClick="currentView.countryCode=\'';
    countryHTML += (
        code + '\'; showDetails(); return false; ">' + name + '</a>');
    if (code == 'EUC' || code == 'EU-27') {
      countryHTML += tooltipHtml(code);
    }
    td3.append(countryHTML);

    slice.push([td1, td3, td2, td4]);
  }

  return slice;
}

