/*
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.
*/

google.load('earth', '1');
google.load('maps', '2.99');  // For JS geocoder

var ge = null;
var geocoder;


function init() {
  save_settings();
  geocoder = new GClientGeocoder();
  google.earth.createInstance('map3d', initCB, failureCB);
}

var initialized = false;
var polygons_initialized = false;
var colors_initialized = false;
var colors = {}
var styles = {}
var links = {}
var sector_total = 'total';
// Following the order in the data files.
var individual_sectors = ['commercial', 'industrial', 'residential', 'electric_production', 'onroad', 'nonroad', 'aircraft', 'unknown'];
var all_sectors = [sector_total].concat(individual_sectors);
var name_for_sector = {
  'electric_production': 'Electric prod'
};
var color_for_sector = {
  'aircraft': '87cefa',
  'commercial': 'ffff00',
  'electric_production': 'ff0000',
  'industrial': '000000',
  'nonroad': '00ff00',
  'onroad': '00ffff',
  'residential': 'ff7700',
  'unknown': 'faebd7'
};
var all_levels = ['state', 'county'];
var all_stats = ['abs', 'per'];

function get_all_layers() {
  var result = {};
  for (var i=0; i<all_levels.length; i++) {
    var level = all_levels[i];
    for (var j=0; j<all_stats.length; j++) {
      var stat = all_stats[j];
      for (var k=0; k<all_sectors.length; k++) {
        var sector = all_sectors[k];
        for (var layer in get_layer_names(level, stat, sector)) {
          result[layer] = 1;
        }
      }
    }
  }
  result['cem_raw_abs'] = 1;
  result['airport_raw_abs'] = 1;
  return result;
}

function get_nl(kml_url) {
  var nl = ge.createNetworkLink('');
  var link = ge.createLink('');
  link.setHref(kml_url);
  nl.setLink(link);
  nl.setVisibility(false);
  ge.getGlobe().getFeatures().appendChild(nl);
  return nl;
}

var legend_dict = null;
var current_layers = [];
var polygons = {};
var show_icons = '';
var show_polygons = '';

var current_view = {
  'airport': '',
  'cem': '',
  'fips': '',
  'level': '',
  'sector': '',
  'stat': '',
  'state_abbr': '',
  'top_hidden': true
};

function get_layer_name(level, stat, sector) {
  stat = stat || current_view.stat;
  sector = sector || current_view.sector;
  level = level || current_view.level;
  return level + '_' + stat + '_' + sector;
}

function get_layer_names(level, stat, sector) {
  result = {}
  if (current_view.cem) {
    result['cem_raw_abs'] = 1;
  }
  if (current_view.airport) {
    result['airport_raw_abs'] = 1;
  }
  var filename = get_layer_name(level, stat, sector);
  result[filename] = 1;
  return result;
}

function change_border(event, set) {
  var p = event.getTarget();
  if (!p.getStyleSelector()) {
    p.setStyleSelector(ge.createStyle(''));
  }

  var color;
  if (set == 1) {
    color = 'ffcccccc';
  }
  else {
    color = 'ffff0000';
  }
  var lineStyle = p.getStyleSelector().getLineStyle();
  lineStyle.getColor().set(color);
}

var name_for_data_key = {
  't': 'Total'
}

function clear_details() {
  current_view.selection = undefined;
  $('#details').empty();
}

function get_data_key() {
  return current_view.level + '_' + current_view.stat;
}

function show_details() {
  var data_key = get_data_key();
  if (! (data_key in all_data)) {
    return;
  }
  var area_data = all_data[data_key];
  var area_key;
  if (current_view.level == 'state') {
    area_key = current_view.state_abbr;
  } else {
    area_key = 'f' + Number(fips);
  }
  if (! (area_key in area_data)) {
    return;
  }

  var data = area_data[area_key];
  var details = $('#details');

  var name = data['name'];

  if (current_view.level == 'county') {
    name += (', ' + current_view.state_abbr);
  }
  var outer_table = $('<table></table>').addClass('box');
  var header_tr = $('<tr></tr>');
  var header_th = $('<th></th>').attr('colspan', 2);
  header_th.append($('<div></div>').text(name));
  header_tr.append(header_th);
  outer_table.append(header_tr);

  var outer_tr = $('<tr></tr>');
  outer_table.append(outer_tr);
  var chart_td = $('<td></td>');
  outer_tr.append(chart_td);

  var data_td = $('<td></td>');
  outer_tr.append(data_td);

  var inner_table = $('<table></table>').addClass('left');
  data_td.append(inner_table);

  var all_values = [];
  for (var i=0; i<all_sectors.length; i++) {
    var sector = all_sectors[i];
    abbr = sector.substring(0,1);
    if (sector != sector_total && (abbr in data)) {
      all_values.push(parseFloat(data[abbr]));
    }
  }

  var max_value = array_max(all_values);
  values = [];
  color_list = [];
  labels = [];

  for (var i=0; i<all_sectors.length; i++) {
    var sector = all_sectors[i];
    abbr = sector.substring(0,1);
    if (abbr in data) {
      value = data[abbr];
      var tr = $('<tr></tr>');
      var background_color = 'ffffff';
      if (i == 0) {
        background_color = 'dddddd';
      } else if (i % 2 == 0) {
        background_color = 'eeeeee';
      }
      tr.css('background-color: #' + background_color);
      inner_table.append(tr);
      label = '';

      if (sector in name_for_sector) {
        label = name_for_sector[sector];
      } else {
        label = uc_first(sector);
      }

      $('<td></td>').addClass('left').css('font-weight', 'bold').text(label).appendTo(tr);
      $('<td></td>').css('text-align', 'right').text(int_with_commas(value)).appendTo(tr);
      if (sector != sector_total && value > 0.01 * max_value) {
        values.push(value);
        color_list.push(color_for_sector[sector]);
        labels.push(label);
      }
    }
  }

  if (values.length > 0) {
    var value_string = values.join(',');
    var color_string = color_list.join(',');
    var label_string = labels.join('%7c');
    var url = 'http://chart.apis.google.com/chart?chs=280x120&chd=t:' + value_string + '&cht=p&chds=0,'+max_value+'&chco=' + color_string + '&chf=bg,s,00000000&chl=' + label_string;
    chart_td.append($('<img></img>').attr('src', url));
  }


  details.empty();
  details.append(outer_table);

  change_top_list();
}

function address_callback(address) {
  var zip = undefined;
  var state_abbr = '';
  if (!address || !'Placemark' in address) {
    zip = 'No address found';
  } else {
    for (var i in address.Placemark) {
      var p = address.Placemark[i];
      if (! ('AddressDetails' in p)) {
        continue;
      }
      if (! ('Country' in p['AddressDetails'])) {
        continue;
      }
      if (! ('AdministrativeArea' in p['AddressDetails']['Country'])) {
        continue;
      }
      var area =  p['AddressDetails']['Country']['AdministrativeArea'];
      if (! ('AdministrativeAreaName' in area)) {
        continue;
      }
      state_abbr = area['AdministrativeAreaName'];
      if (! ('Locality' in area)) {
        continue;
      }
      if (! ('PostalCode' in area['Locality'])) {
        continue;
      }
      if (! ('PostalCodeNumber' in area['Locality']['PostalCode'])) {
        continue;
      }
      zip = area['Locality']['PostalCode']['PostalCodeNumber'];
      break;
    }
    if (state_abbr && zip)  {
      // Get rid of a possible initial zero by converting zip to a number
      fips = zip_to_fips['z' + Number(zip)]
      current_view.fips = fips;
      current_view.state_abbr = state_abbr.toUpperCase();
      show_details();
      return;
    }
  }
  $('#details').html('<p>No data');
}

function clickHandler(event) {
  //var coord = GLatLng(event.getLatitude(), event.getLongitude());
  //geocoder.getLocations(coord, address_callback);
  url = 'http://maps.google.com/maps/geo?q=' + event.getLatitude() + ',' + event.getLongitude() + '&oe=utf8&sensor=false&key=ABQIAAAAwIVZ5JhWdW8Oj8zK-haeGhThAIVEk1S2P1dEkWf5XNxypBUOYxTh-RDjcCRBbhs8GMc23o5g4V4MzA'
  $.get(url, null, address_callback, 'jsonp');
}

function mouseOverHandler(event) {
  change_border(event, 1);
}

function mouseOutHandler(event) {
  change_border(event, 0);
}

var polygons_loaded = 0;
var polygons_expected = 2;
var colors_loaded = 0;
var colors_expected = 32;

function json_done(data) {
  change_top_list();
}

function color_done(data) {
  colors_loaded += 1;
  if (colors_loaded == colors_expected) {
    colors_initialized = true;
    change_view();
  }
}

function polygon_done(doc) {
  var folder = doc.getFeatures().getFirstChild();
  var id = folder.getId();
  folder.setVisibility(false);
  polygons[id] = folder;
  ge.getFeatures().appendChild(folder);

  google.earth.addEventListener(folder, 'click', clickHandler);
  polygons_loaded += 1;
  if (polygons_loaded == polygons_expected) {
    polygons_initialized = true;
    change_view();
  }

  //google.earth.addEventListener(folder, 'mouseover', mouseOverHandler);
  //google.earth.addEventListener(folder, 'mouseout', mouseOutHandler);
}

function initCB(object) {
  all_data = {};
  $.getJSON('all_data_state_abs.js');
  $.getJSON('all_data_state_per.js');
  $.getJSON('all_data_county_abs.js');
  $.getJSON('all_data_county_per.js');
  $.getJSON('zip_to_fips.js');
  ge = object;
	ge.getNavigationControl().setVisibility(ge.VISIBILITY_SHOW);
  var la = ge.createLookAt('');
  la.set(40, -100, 5000000, ge.ALTITUDE_RELATIVE_TO_GROUND,
		0, 0, 4000);
  ge.getView().setAbstractView(la);
  ge.getWindow().setVisibility(true);
  var location = document.location.href;
  var parent_dir = location.substring(0, location.lastIndexOf('/')+1);
  var all_layers = get_all_layers();
  for (var link_name in all_layers) {
		links[link_name] = get_nl(parent_dir + link_name + '.kml');
    $.getJSON('color_' + link_name + '.js', color_done);
  }
  google.earth.fetchKml(ge, parent_dir + 'polygons_state.kmz', polygon_done);
  google.earth.fetchKml(ge, parent_dir + 'polygons_county.kmz', polygon_done);

  initialized = true;
  change_view();
}

function failureCB(object) {
}

function submitLocation() {
  var address = $('#address').val();
  geocoder.getLatLng(
    address,
    function(point) {
      if (point && ge != null) {
        var la = ge.createLookAt('');
        la.set(point.y, point.x, 100, ge.ALTITUDE_RELATIVE_TO_GROUND,
               0, 0, 4000);
        ge.getView().setAbstractView(la);
    }
    }
  );
}

function refreshPlugin() {
  // Workaround to avoid moving mouse to make changes appear
  var camera = ge.getView().copyAsCamera(ge.ALTITUDE_RELATIVE_TO_GROUND);
  ge.getView().setAbstractView(camera);
}

function show_legend() {
  if (legend_dict == null) {
    setTimeout(show_legend, 1000);
    return;
  }
	source_name = uc_first(current_view.sector) + ' CO<sub>2</sub> sources';
  source_name = source_name.replace('_', ' ');
  if (current_view.stat == 'per') {
    source_name += ', per capita';
  }
	$('#legend').html(source_name);
	$('#min_value').html(legend_dict['min']);
	$('#mid_value').html(legend_dict['mid']);
	$('#max_value').html(legend_dict['max']);
	$('#unit').html(legend_dict['unit']);
	$('img.scale').attr('src', 'circle_' + current_view.sector + '.png');

}

function save_settings() {
  current_view.sector =  $('.sector:checked').val();
  current_view.stat =  $('.stat:checked').val();
  current_view.level =  $('.level:checked').val();
  current_view.cem = $('#cem')[0].checked;
  current_view.airport = $('#airport')[0].checked;

  var show_which =  $('.show_which:checked').val();
  show_polygons = (show_which == 'polygons' || show_which == 'both');
  show_icons = (show_which == 'icons' || show_which == 'both');

  current_layers = get_layer_names();

}

Function.prototype.curry = function()
 {
   var method = this, args = Array.prototype.slice.call(arguments);
   return function()
   {
     return method.apply(this, args.concat(Array.prototype.slice.call(arguments)));
   };
 };

sort_by_field = function(field, a, b) {
  // Push undefined values to the bottom
  if (! (field in a)) {
    a[field] = 0;
  }
  if (! (field in b)) {
    b[field] = 0;
  }
  return b[field] - a[field];
}

function change_top_list() {
  var list = [];
  var list_level = '';
  if (current_view.state_abbr == '') {
    list_level = current_view.level;
  } else {
    list_level = 'county';
  }
  data_key = list_level + "_" + current_view.stat;
  dict = all_data[data_key];
  state = current_view.state_abbr;
  var sector_key = current_view.sector.charAt(0);

  // If nothing is selected, use all US data.
  // If a state or a county was clicked on, show
  // top counties for that state.
  for (var fips in dict) {
    if (state == '' || dict[fips].s.toUpperCase() == state.toUpperCase()) {
      var item = dict[fips];
      if (! sector_key in item) {
        item[sector_key] = 0;
      }
      list.push(item);
    }
  }

  if (list.length == 0) {
    return;
  }

  var top_length = Math.min(20, list.length);

  list.sort(sort_by_field.curry(sector_key));
  for (var i=0; i<5; i++) {
    //alert(list[i][sector_key]);
  }

  var title;
  if (current_view.state_abbr == '') {
    title = "the US";
  } else {
    title = all_data.state_abs[current_view.state_abbr]["name"];
  }
  var table = $('<table></table>').addClass('box').attr('width', '100%');
  var header_tr = $('<tr></tr>');
  var header_th = $('<th></th>').attr('colspan', 2);
  header_th.append($('<div></div>').html("Top " + top_length + " sources in " + title + "<br>" + legend_dict['unit']));
  header_tr.append(header_th);
  table.append(header_tr);

  for (var i=0; i<top_length; i++) {
    var item = list[i];

    var name = item['name'];
    if (list_level == 'county') {
      name += (', ' + item['s']);
    }

    var tr = $('<tr></tr>');
    $('<td></td>').css('text-align', 'left').text(name).appendTo(tr);
    value = item[sector_key];
    $('<td></td>').css('text-align', 'right').text(int_with_commas(value)).appendTo(tr);
    table.append(tr);
  }

  var top_list = $('#top_list');
  top_list.empty();
  top_list.append(table);
}

function toggle_top() {
  var display, new_text;
  if (current_view.top_hidden) {
    display = 'inline-block';
    new_text = 'Hide table';
  } else {
    display = 'none';
    new_text = 'Show table';
  }
  current_view.top_hidden = !current_view.top_hidden;
  $('#top_div').attr('style', 'display: ' + display);
  $('#toggle_top').text(new_text);
}


function change_view() {
  if (!initialized || !polygons_initialized || !colors_initialized) {
    return;
  }

  old_layers = current_layers;
  old_level = current_view.level;
  current_view.state_abbr = '';
  save_settings();

  for (var old_link in old_layers) {
    if (! (old_link in current_layers)) {
      if (old_link in links) {
        links[old_link].setVisibility(false);
      }
    }
  }
  if (old_level != current_view.level) {
    polygons[old_level].setVisibility(false);
    clear_details();
  }
  for (var new_link in current_layers) {
    if (! (new_link in links)) {
      alert(new_link + ' not loaded');
    } else {
      links[new_link].setVisibility(show_icons);
    }
  }

  legend_dict = null;
  $.getJSON(new_link+'.js', json_done);

  var location = document.location.href;
  var parent_dir = location.substring(0, location.lastIndexOf('/')+1);
  google.earth.fetchKml(ge, parent_dir + 'polygons_state.kmz', change_poly_style);

  setTimeout(show_legend, 1000);
  //setTimeout(refreshPlugin, 1000);
  setTimeout(refreshPlugin, 5000);
  //setTimeout(refreshPlugin, 10000);
}

function change_poly_style() {
  var placemarks = polygons[current_view.level].getFeatures().getChildNodes();
  var layer_colors = colors[get_layer_name()];
  for (var i=0; i<placemarks.getLength(); i++) {
    var p = placemarks.item(i);
    var style;
    var color = 'e0' + layer_colors[p.getId()];
    if (color in styles) {
      style = styles[color];
    } else {
      style = ge.createStyle('');
      style.getPolyStyle().getColor().set(color);
      styles[color] = style;
    }

    p.setStyleSelector(style);

  }

  polygons[current_view.level].setVisibility(show_polygons);

}

function print_choices(name, array) {
  for (var i=0; i<array.length; i++) {
    var item = array[i];
    var checked = '';
    if (i==0) {
      checked = 'checked';
    }
    document.write('<input type="radio" ' + checked + ' name="' + name + '" value="' + item + '" onClick="change_view()">' + item + '<br>\n');
  }
}
