var walkspeed = 4000 / 60.0 / 60.0;
var cycspeed = 20000 / 60.0 / 60.0;

var debugstr = "";

var redicon = new GIcon();
redicon.image = "http://www.google.com/mapfiles/marker.png";
redicon.shadow = "http://www.google.com/mapfiles/shadow50.png";
redicon.iconSize = new GSize(10, 17);
redicon.shadowSize = new GSize(19, 17);
redicon.iconAnchor = new GPoint(5,17);

var greenicon = new GIcon();
greenicon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";
greenicon.shadow = "http://www.google.com/mapfiles/shadow50.png";
greenicon.iconSize = new GSize(10, 17);
greenicon.shadowSize = new GSize(19, 17);
greenicon.iconAnchor = new GPoint(5,17);

/* This function loads a script programatically */
/* Doesn't work safari */
function load_script(src) {
  var e = document.createElement("script");
  e.src = src;
  e.type="text/javascript";
  document.getElementsByTagName("head")[0].appendChild(e);
}

function area_of_polygon(points) {
  var sum = 0
  for (var i = 0; i < points.length - 1; i++) {
    sum += (points[i].x * points[i+1].y - points[i+1].x * points[i].y)
  }
  return sum / 2;
}

function center_of_mass(points) {
  var a = area_of_polygon(points) * 6;
  var c_x = 0;
  var c_y = 0;
  for (var i = 0; i < points.length - 1; i++) {
    var foo = (points[i].x * points[i+1].y - points[i+1].x * points[i].y);
    c_x += (points[i].x + points[i+1].x) * foo;
    c_y += (points[i].y + points[i+1].y) * foo;
  }
  c_x /= a;
  c_y /= a;
  return new GPoint(c_x, c_y);
}

function route_xml(points) {
  var output = "";
  output += "&lt;route&gt;\n";
  for (var i=0; i < points.length; i++) {
    output += "  &lt;point&gt; lat=\"" + points[i].y + "\" lng=\"" + points[i].x + "\"/&gt\n"; 
  }
  output += "&lt;/route&gt;";
  return output;
}

function fmt(num, dp) {
  var exp = Math.pow(10, dp);
  return  Math.round(num * exp) / exp;
}

function lnglat_markup(lnglat, size) {
  var latstr = "";
  var lngstr = "";
  var i = 0;

  while (size < 1.0) {
    i = i + 1;
    size = size * 10;
  }

  if (lnglat.y < 0) {
    latstr = fmt(-lnglat.y, i) + "S";
  } else {
    latstr = fmt(lnglat.y, i) + "N";
  }
  
  if (lnglat.x < 0) {
    lngstr = fmt(-lnglat.x, i) + "W";
  } else {
    lngstr = fmt(lnglat.x, i) + "E";
  }
  
  return "(" + latstr + ",&nbsp;" + lngstr + ")";
}


function time_markup(seconds) {
  if (seconds > 3600 * 24) {
    days = Math.floor(seconds / (3600 * 24));
    hours = Math.floor((seconds - days * (3600 * 24)) / 3600);
    return days + " days " + fmt(hours, 0) + " hours";
  }
  if (seconds > 3600) {
    hours = Math.floor(seconds / 3600);
    minutes = Math.floor((seconds - hours * 3600) / 60);
    return hours + " hours " + fmt(minutes, 0) + " min";
  }
  if (seconds > 60) {
    mins = Math.floor(seconds / 60);
    seconds = seconds - mins * 60;
    return mins + " min " + fmt(seconds, 0) + " s";
  }
    
  return fmt(seconds, 2) + " s";
} 

function dist_markup(metres) {
  if (metres > 1000) {
    return fmt(metres / 1000, 2) + " km";
  } else {
    return fmt(metres, 2) + " m";
  }
} 

var debug_on = 1;
function debug(txt) {
	alert(txt);
}

/* Convert degress to radians */
function deg2rad(deg) {
  return deg / (180 / Math.PI);
}

/* Copy Object Function */
function copy_obj(o) {
	var c = new Object();
	for (var e in o) {
		if (typeof o[e] =='array' && o[e].constructor == Array) {
			c[e] = c[e].copy();
		}
		else {
			c[e] = o[e]; 
		}
	}
          return c;
}

/* Calculate distance between two points */
function point_distance(a, b) {
  var r = 6378700;
  var lat1 = a.y;
  var lat2 = b.y;
  var lon1 = a.x;
  var lon2 = b.x;
  var dist = r * Math.acos(Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + 
			   Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * 
			   Math.cos(deg2rad(lon1 - lon2)));
  return dist;
}

function distance(points) {
  dist = 0;
  for (var i=1; i < points.length; i++) {
    dist += point_distance(points[i-1], points[i]);
  }
  return dist;
}

/* Create a new google map */
function newMap() {
    var map = new GMap(document.getElementById("map"));
    map.setMapType(_SATELLITE_TYPE); 
    map.addControl(new GLargeMapControl());
    map.addControl(new GMapTypeControl());
    return map;
}

function markup_location(location) {
  var col = "#ff0000";
  var name = location.getAttribute("name");
  var polygon = location.getElementsByTagName("polygon")[0];
  var markers = polygon.getElementsByTagName("point");
  var points2 = new Array();
  for (var i = 0; i < markers.length; i++) {
    points2[points2.length] = new GPoint(parseFloat(markers[i].getAttribute("lng")),
					 parseFloat(markers[i].getAttribute("lat")));
    point = points2[points2.length-1];
  }
  points2[points2.length] = points2[0];
  point = center_of_mass(points2);
  var marker = new GMarker(point);
  marker.save = 1;
  map.addOverlay(marker);
  GEvent.addListener(marker, "click", function () {
    var descelem = location.getElementsByTagName("description")[0];
    var description = descelem.firstChild.data;
    var data = "<div class=\"popup\"><strong> " + name + "</strong><br /> " + description;
    data += "<br /><a href=\"javascript:void(0)\" onClick=\"show_update_form('" + name + "', '" + description + "')\">Update</a></div>";
    marker.openInfoWindowHtml(data);
  });
  
  var foolastlay = new GPolyline(points2, col, 2);
  map.addOverlay(foolastlay);
}

function overlay_locations(url_name) {
  var request = GXmlHttp.create();
  request.open("GET", url_name, true);
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;
      var locations = xmlDoc.documentElement.getElementsByTagName("location");
      for (var i=0; i < locations.length; i++) {
	markup_location(locations[i]);
      }
    }
  }
  request.send(null);    
}

function loadxml(url, fn) {
 var request = GXmlHttp.create();
  request.open("GET", url, true);
  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      fn(request.responseXML.documentElement);
    }
  }
  request.send(null);    
}


function getObjSize(obj){
  if(obj.style.width && obj.style.height){
    var e = new Object();
    e.width = parseInt(obj.style.width.replace(/px/, ''));
    e.height = parseInt(obj.style.height.replace(/px/, ''));
    return e;
  }
  return null;
}

function getWindowSize(){
  var e = new Object();
  if(window.self && self.innerWidth){
    e.width = self.innerWidth;
    e.height = self.innerHeight;
  }else if(document.documentElement && document.documentElement.clientHeight){
    e.width = document.documentElement.clientWidth;
    e.height = document.documentElement.clientHeight;
  }else{
    e.width = document.body.clientWidth;
    e.height = document.body.clientHeight;
  }
  return e;
}

function js_url(fn_name, description) {
  return '<a href="javascript:void(0)" onClick="' + fn_name + '">' + description + '</a>';
}

function js_url(fn_name, description, toolid) {
  return '<a href="javascript:void(0)" onClick="' + fn_name + '"><span id="' + toolid + '">' + description + '</span></a>';
}


/* 
 How I use XMLRPC
   Arg 1 is always username
   Arg 2 is always password hash
   Arg n-> arguments
   Arg n-1 function to call on completion
*/

function add_str_node(arg) {
  return "<param><value><string>" + arg + "</string></value></param>"
}

function add_float_node(arg) {
  return "<param><value><double>" + arg + "</double></value></param>"
}


function add_float_member(arg, name) {
  return "<member><name>" + name + "</name><value><double>" + arg + "</double></value></member>"
}

function add_path_node(arg) {
  var paramstr = "<param><array><data>";
  for (var i=0; i < arg.length; i++) {
    paramstr += "<struct>" + add_float_member(arg[i].x, "lng") + add_float_member(arg[i].y, "lat") + "</struct>"
  }
  paramstr += "</data></array></param>";
  return paramstr;
}

function make_xmlrpc(url, name, argspec, type) {
  return function () {
    var args;
    if (argspec == "") {
      args = Array(0);
    } else {
      args = argspec.split(",");
    }
    if (arguments.length != args.length + 2) {
      debug("Error!");
    }
    var request_str = "<methodCall><methodName>" + name + "</methodName>";
    request_str += "<params>";
    request_str += add_str_node("foo"); //login.user);
    request_str += add_str_node("bar"); //login.password);
    for (var i=0; i < args.length; i++) {
      if (args[i] == "s") {
	request_str += add_str_node(arguments[i]);
      } 
      if (args[i] == "f") {
	request_str += add_float_node(arguments[i]);
      } 
      if (args[i] == "path") {
	request_str += add_path_node(arguments[i]);
      }
    }

    request_str += "</params>";
    request_str += "</methodCall>";

    var fn = arguments[args.length];
    var exc_fn = arguments[args.length+1];

    var request = GXmlHttp.create();

    request.open("POST", url, true);

    request.onreadystatechange = function() {
      if (request.readyState == 4) {
	var xmlDoc = request.responseXML;
	/* Evil way of getting stuff out */
	if (request.status != 200) {
		exc_fn("HTTP Error: " + request.status);
	} else {
		if (type == 0) {
			if (xmlDoc.documentElement.getElementsByTagName("fault").length == 1) {
				exc_fn(xmlDoc.documentElement.getElementsByTagName("fault")); /* Should do more here */
			} else {
				var ret_val = xmlDoc.documentElement.getElementsByTagName("value")[0].firstChild.firstChild.textContent
					fn(ret_val);
			}
		} else {
			fn(xmlDoc.documentElement);
		}
	}
      }
    }
    request.send(request_str);
  }
}

function make_rest2(url, argspec) {
  return function () {
    var args;
    if (argspec == "") {
      args = Array(0);
    } else {
      args = argspec.split(",");
    }
    if (arguments.length - 1 != args.length) {
      debug("Error!" + arguments.length - 1 + " != "  + args.length);
    }
    var request_str = url + "?";
    for (var i=0; i < args.length; i++) {
	    request_str += args[i] + "=" + arguments[i] + "&";
    }

    var fn = arguments[args.length];

    var request = GXmlHttp.create();
    request.open("GET", request_str, true);
    request.onreadystatechange = function() {
      if (request.readyState == 4) {
	var xmlDoc = request.responseXML;
	fn(xmlDoc.documentElement);
      }
    }
    request.send(null);
  }
}


function make_rest(url, argspec) {
  return function () {
    var args;
    if (argspec == "") {
      args = Array(0);
    } else {
      args = argspec.split(",");
    }
    if (arguments.length - 1 != args.length) {
      debug("Error!" + arguments.length - 1 + " != "  + args.length);
    }
    var request_str = "url=" + url + "&";
    for (var i=0; i < args.length; i++) {
	    request_str += args[i] + "=" + arguments[i] + "&";
    }

    var fn = arguments[args.length];

    var request = GXmlHttp.create();
    request.open("GET", "rest.cgi?" + request_str, true);
    request.onreadystatechange = function() {
      if (request.readyState == 4) {
	var xmlDoc = request.responseXML;
	fn(xmlDoc.documentElement);
      }
    }
    request.send(null);
  }
}

degree_per_pixel = 1.4065;
max_zoom = 17;

function zoom_level(bounds) {
	width = bounds.maxX - bounds.minX;
	height = bounds.maxY - bounds.minY;
	w_zoom = max_zoom - Math.floor(Math.log(1.40625 / (width / map.viewSize.width)) / Math.log(2));
	h_zoom = max_zoom - Math.floor(Math.log(1.40625 / (height / map.viewSize.height)) / Math.log(2));
	if (w_zoom < 0) {
		w_zoom = 0;
	}
	if (h_zoom < 0) {
		h_zoom = 0;
	}
	if (w_zoom > h_zoom) {
		return w_zoom;
	} else {
		return h_zoom;
	}
}

function center_of_bounds(bounds) {
	return new GPoint((bounds.maxX + bounds.minX) / 2, (bounds.maxY + bounds.minY) / 2);
}

function path_bounds(points) {
	var maxX = points[0].x;
	var minX = points[0].x;
	var maxY = points[0].y;
	var minY = points[0].y;

	for (var i=1; i < points.length; i++) {
		if (points[i].x > maxX) {
			maxX = points[i].x;
		} else if (points[i].x < minX) {
			minX = points[i].x;
		}
		if (points[i].y > maxY) {
			maxY = points[i].y;
		} else if (points[i].y < minY) {
			minY = points[i].y;
		}
	}
	
	return new GBounds(minX, minY, maxX, maxY);
}
