/***************************************************************************
 *   Copyright (C) 2007, Paul Lutus                                        *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
// deal with Google's access key requirement
if(location.href.match(/localhost/)) {
  key = "ABQIAAAAz5b55iZHhPKPMCXkZR710hT2yXp_ZAY8_ufC3CFXhHIE1NvwkxS4W17URr0Fwsl78YDZqCnaFF1Ecg";
}
else if (location.href.match(/pl-alpha/)) {
  key = "ABQIAAAAz5b55iZHhPKPMCXkZR710hSRLDufbmhQ9q5xpBRcZtK7smSYOBRz44JngyRAL29621TBNI9sAyLyiQ";
}
else if (location.href.match(/arachnoid.com/)) {
  key = "ABQIAAAAz5b55iZHhPKPMCXkZR710hSnEynZv7_tMsg_dY2XOMwxxbBswhQvgE21ngtmsUaFDMQzc4e1tI6Jng";
}
document.write("<script src=\"http://maps.google.com/maps?file=api&amp;v=2.x&amp;key=" + key + "\" type=\"text/javascript\"></script>");
// initialization
addEvent(window,"load",perform_load);
addEvent(window,"unload",perform_unload);
// addEvent(document,"click",on_click);
// function to add an event listener
function addEvent(o,e,f) {
  if (o.addEventListener) {
    o.addEventListener(e,f,false);
    return true;
  }
  else if (o.attachEvent) {
    return o.attachEvent("on"+e,f);
  }
  else {
    return false;
  }
}
// cookie handling code
function read_cookie()
{
  var path = window.location.pathname;
  var array = 0;
  var a = document.cookie.indexOf(path);
  if(a != -1) {
    a += path.length + 1;
    var b = document.cookie.indexOf(";",a);
    if(b == -1) {
      b = document.cookie.length;
    }
    var cookie = unescape(document.cookie.substring(a,b));
    if(cookie != '') {
      var unesc_cookie = unescape(cookie);
      //alert("read cookie: " + unesc_cookie);
      array = unesc_cookie.split("\t");
    }
  }
  return array;
}
function write_cookie(array) {
  var cookie = array.join("\t");
  //alert("write cookie: " + cookie);
  var esc_cookie = escape(cookie);
  var duration = new Date(new Date().getTime() + 30 * 24 * 60 * 60 * 1000);
  document.cookie=window.location.pathname+"="+esc_cookie+"; expires=" + duration.toGMTString();
}
function read_defaults(perform)
{
  if (document.createElement) {
    var array = read_cookie();
    if(array != 0) {
      var len = array.length;
      if(len == 11 && perform) {
        cookie_available = true;
        cur_distance_visible = array[0];
        cur_distance_units = array[1];
        cur_map_type = array[2];
        cur_zoom = array[3];
        cur_lat = array[4];
        cur_lng = array[5];
        cur_movable = array[6];
        cur_lines = array[7];
        cur_mapsize = array[8];
        cur_search_arg = array[9];
        cur_data = array[10];
      }
    }
  }
  cur_zoom = eval(cur_zoom);
  document.getElementById("mapdata").value = cur_data;
  document.getElementById("mapsize").selectedIndex = cur_mapsize;
  document.getElementById("movable").checked = eval(cur_movable);
  document.getElementById("distance").checked = eval(cur_distance_visible);
  document.getElementById("polyline").checked = eval(cur_lines);
  document.getElementById("searchfield").value = cur_search_arg;
}
function wrap_tag(data,tag,extra) {
  return "<" + tag + " " + extra + ">" + data + "</" + tag + ">\n";
}
var map;
var cookie_available = false;
var cur_distance_visible = false;
var cur_distance_units = 0;
var cur_map_type = 0;
var cur_zoom = 16;
var cur_lat = 38.89393880976647;
var cur_lng = -77.03643321990967;
var cur_data = "";
var cur_search_arg;
var cur_movable = false;
var cur_mapsize = 1; // default 640x480
var marker_array = new Object();
var cur_lines = true;
var line_array = new Array();
var line_width = 3;
var line_opacity = 0.8;
var line_term = "\n";
var default_data =
"38.89536,-77.03916,0,New0,New Description\n"
+ "38.89536,-77.03375,0,New1,New Description\n"
+ "38.89210,-77.03364,0,New2,New Description\n"
+ "38.89210,-77.03948,0,New3,New Description\n"
+ "38.89501,-77.03948,0,New4,New Description\n";

function perform_load() {
  read_defaults(true);
  set_movable();
  set_distance_display();
  set_lines();
  resize_map();
  if (GBrowserIsCompatible()) {
    emap = document.getElementById("gpsmap");
    map = new GMap2(emap);
    map.setCenter(new GLatLng(cur_lat,cur_lng),cur_zoom);
    map.setZoom(cur_zoom);
    map.setMapType(map.getMapTypes()[cur_map_type]);
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    map.addControl(new GSmallZoomControl());
    map.addControl(new GScaleControl());
    GEvent.addListener(map, "maptypechanged", function() {
        cur_map_type = get_map_type();
        process_lines();
    });
    //map.addControl(new GOverviewMapControl());
    map.enableScrollWheelZoom();
    // don't allow the scroll wheel to scroll
    // the page as well as zoom the map
    GEvent.addDomListener(emap, "DOMMouseScroll", wheelevent);
    emap.onmousewheel = wheelevent;
    document.getElementById("searchfield").onkeypress = function(event) {
      var e = (event ? event : window.event);
      var key = e.keyCode || e.charCode;
      if(key == 13) {
        search_for(1);
      }
    };
   read_data_list();
  }
}
// prevent scroll wheel zoom
// from also scrolling page
function wheelevent(e)
{
  if (!e) e = window.event;
  if (e.preventDefault) e.preventDefault();
  e.returnValue = false;
}
function get_map_type() {
  types = map.getMapTypes();
  cmt = map.getCurrentMapType();
  for(var i = 0;i < types.length;i++) {
    if(types[i] == cmt) {
      return i;
    }
  }
  return 0;
}
function perform_unload() {
  set_movable();
  set_distance_display();
  set_lines();
  cur_map_type = get_map_type();
  cur_zoom = map.getZoom();
  latlng = map.getCenter();
  cur_lat = latlng.lat();
  cur_lng = latlng.lng();
  cur_data = document.getElementById("mapdata").value;
  cur_search_arg = document.getElementById("searchfield").value;
  //cur_data = cur_data.replace(/\r/g,"");
  var array = new Array(cur_distance_visible,cur_distance_units,cur_map_type,cur_zoom,cur_lat,cur_lng,cur_movable,cur_lines,cur_mapsize,cur_search_arg,cur_data);
  write_cookie(array);
  GUnload();
}
function add_marker(pos,title,desc,altitude) {
  var text_key = title;
  var marker;
  if(typeof(marker_array[text_key]) != "undefined") {
    var n = 1;
    var tag;
    while(true) {
      tag = text_key + "_" + n;
      if(typeof(marker_array[tag]) == "undefined") {
        break;
      }
      n++;
    }
    text_key = tag;
  }
  var opts = new Object();
  opts.draggable = cur_movable;
  opts.title = text_key + "|" + desc;
  marker = new GMarker(pos,opts);
  map.addOverlay(marker);
  marker.text = text_key;
  marker.desc = desc;
  marker.altitude = altitude;
  GEvent.addListener(marker, "click", function() {
      handle_marker_click(marker);
  });
  marker_array[text_key] = marker;
  GEvent.addListener(marker, "dragend", marker_moved);
  return marker;
}
function handle_marker_click(marker) {
  var old_text = marker.text;
  var input = document.createElement('input');
  var block = document.createElement('div');
  var prompt = document.createElement('span');
  var text1 = document.createTextNode('Edit name|description, press Enter to submit,');
  var text2 = document.createTextNode('delete text to delete marker:');
  prompt.appendChild(text1);
  prompt.appendChild(document.createElement('br'));
  prompt.appendChild(text2);
  prompt.appendChild(document.createElement('p'));
  block.appendChild(prompt);
  block.appendChild(input);
  block.setAttribute('class','edit_window');
  block.className = 'edit_window';
  input.value = old_text;
  input.setAttribute("size","40");
  // set focus on input field
  GEvent.addListener(marker, "infowindowopen", function() {
      input.focus();
  });
  // detect Enter key, retrieve user entry
  input.onkeypress = function(event) {
    var e = (event ? event : window.event);
    var key = e.keyCode || e.charCode;
    if(key == 13) {
      marker.closeInfoWindow();
      var new_text = input.value;
      if(old_text != new_text) {
        marker_array[old_text] = 0;
        if(new_text.length > 0) {
          marker.text = new_text;
          marker_array[new_text] = marker;
        }
        else { // remove marker if text deleted
          map.removeOverlay(marker);
        }
        update_marker_list();
      }
    }
  };
  marker.openInfoWindow(block);
}
function get_unique_key() {
  var new_marker_index = 1;
  while(true) {
    var nv = "" + new_marker_index;
    while(nv.length < 3) {
      nv = "0" + nv;
    }
    tag = "New" + nv;
    if(typeof(marker_array[tag]) == "undefined") {
      break;
    }
    new_marker_index++;
  }
  return tag;
}
function create_new_marker() {
  var tag = get_unique_key();
  marker = add_marker(map.getCenter(),tag,"New Description",0);
  update_marker_list();
}
function marker_moved() {
  update_marker_list();
}
function set_fix(v,p) {
  sign = (v < 0)?-1:1;
  v = Math.abs(v);
  v = v.toFixed(p);
  v *= sign;
  vs = "" + v;
  // now put in trailing zeros
  // if required so numbers
  // have the same length
  var p = vs.indexOf(".");
  if(p > 0) {
    while((vs.length - p) < 6) {
      vs += "0";
    }
  }
  return vs;
}
function sort_assoc(array) {
  keys = new Array();
  for(var q in array) {
    keys.push(q);
  }
  keys = keys.sort();
  out = new Object();
  for(i in keys) {
    key = keys[i];
    out[key] = array[key];
  }
  return out;
}
function trim(s) {
  return s.replace(/^\s*(.*?)\s*$/,"$1");
}
function update_marker_list() {
  output = "";
  array = new Array();
  marker_array = sort_assoc(marker_array);
  for(var q in marker_array) {
    var m = marker_array[q];
    if(m != 0) {
      var pos = m.getLatLng();
      var lat = pos.lat();
      var lng = pos.lng();
      lat = set_fix(lat,5);
      lng = set_fix(lng,5);
      array.push(lat + "," + lng + "," + m.altitude + "," + m.text + "," + m.desc);
    }
  }
  if(array.length > 0) {
    output = array.join(line_term) + line_term;
    cur_data = array.join("\n");
  }
  output = trim(output);
  document.getElementById("mapdata").value = output;
  process_lines();
  create_distance_matrix();
}
function set_movable() {
  cur_movable = document.getElementById("movable").checked;
}

function set_distance_display() {
  cur_distance_visible = document.getElementById("distance").checked;
}

function set_lines() {
  cur_lines = document.getElementById("polyline").checked;
}
function read_text_data(data) {
  set_movable();
  set_distance_display();
  set_lines();
  map.clearOverlays();
  marker_array = new Object();
  array = data.split(line_term);
  for(var i = 0;i < array.length;i++) {
    line = trim(array[i]);
    if(line.length > 0) {
      fields = line.split(",");
      if(fields.length >= 5) {
        altitude = fields[2];
        title = fields[3];
        desc = fields[4];
        pos = new GLatLng(fields[0],fields[1]);
        add_marker(pos,title,desc,altitude);
      }
      else {
        alert("Error -- record doesn't have enough fields: " + line);
      }
    }
  }
  update_marker_list();
}
function read_data_list() {
  if(cookie_available || document.getElementById("mapdata").value.length > 0) {
    read_text_data(document.getElementById("mapdata").value);
  }
  else {
    read_text_data(default_data);
  }
}
function erase_all_markers() {
  result = confirm("Okay to erase all markers?");
  if(result) {
    read_text_data("");
  }
}
function resize_map() {
  cur_mapsize = document.getElementById("mapsize").selectedIndex;
  var mapstr = document.getElementById("mapsize").options[cur_mapsize].text;
  array = mapstr.split("x");
  emap = document.getElementById("gpsmap");
  emap.style.width = array[0] + "px";
  emap.style.height = array[1] + "px";
}
function process_lines() {
  set_lines();
  while(line_array.length > 0) {
    line = line_array.pop();
    map.removeOverlay(line);
  }
  if(cur_lines) {
    var line_color = (cur_map_type == 0)?"#0000ff":"#ffff00";
    var old_k = 0;
    for (k in marker_array) {
      if(old_k != 0) {
        var line = new GPolyline([marker_array[old_k].getLatLng(),marker_array[k].getLatLng()],line_color,line_width,line_opacity);
        map.addOverlay(line);
        line_array.push(line);
      }
      old_k = k;
    }
  }
}
// some of the stored "numbers"
// are nothing of the kind,
// so "parseFloat" all of them.
function v_min(a,b) {
  a = parseFloat(a);
  b = parseFloat(b);
  return (a < b)?a:b;
}
function v_max(a,b) {
  a = parseFloat(a);
  b = parseFloat(b);
  return (a > b)?a:b;
}
function box_limits(limits,pos) {
  limits.minLat = v_min(limits.minLat,pos.lat());
  limits.maxLat = v_max(limits.maxLat,pos.lat());
  limits.minLng = v_min(limits.minLng,pos.lng());
  limits.maxLng = v_max(limits.maxLng,pos.lng());
  return limits;
}
function center_on_markers() {
  var limits = {minLat:500,maxLat:-500,minLng:500,maxLng:-500};
  points = 0;
  for (k in marker_array) {
    var m = marker_array[k];
    limits = box_limits(limits,m.getLatLng());
    points++;
  }
  if(points > 0) {
    var sw_pos = new GLatLng(limits.minLat,limits.minLng);
    var ne_pos = new GLatLng(limits.maxLat,limits.maxLng);
    var marker_bounds = new GLatLngBounds(sw_pos,ne_pos);
    var zoom = map.getBoundsZoomLevel(marker_bounds);
    var center = new GLatLng((limits.maxLat+limits.minLat)/2.0,(limits.maxLng+limits.minLng)/2.0);
    map.setCenter(center,zoom);
  }
  else { // no points in array
    alert("No markers have been defined.");
  }
}
function search_for(n) {
  cur_search_arg = document.getElementById("searchfield").value;
  var coder = new GClientGeocoder();
  coder.setViewport(map.getBounds());
  if(n == 0) {
    coder.getLatLng(cur_search_arg,center_on_loc);
  }
  else {
    coder.getLocations(cur_search_arg,mark_loc);
  }
}
function center_on_loc(pos) {
  if(pos) {
    map.setCenter(pos,16);
  }
  else {
    alert("Error: " + cur_search_arg + " not found.");
  }
}
function mark_loc(resp) {
  if(resp.Placemark) {
    var len = resp.Placemark.length;
    for(var i = 0;i < len;i++) {
      var place = resp.Placemark[i];
      var pos = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
      var add = place.address.replace(/\,/g,";");
      var tag = get_unique_key();
      marker = add_marker(pos,tag,add,0);
      if(len == 1) {
        marker.openInfoWindowHtml(place.address);
      }
    }
    update_marker_list();
    center_on_markers();
  }
  else {
    alert("Error: " + cur_search_arg + " not found.");
  }
}

