var tt = window.tt || {}; //application global
 
/*
 * Polygon class
 * 
 * 
 */

function Polygon(lat,lon,lata,lona,sides) 
{
	var me = this;
	me.numsides = sides;
	me.cent = new PM(lat,lon,'centre','ff00ffff');
	me.rad = new PM(lata,lona,'outer','ff8080ff');
	me.setBearDist();
	
	var lineStringPlacemark = ge.createPlacemark('');
	me.lineString = ge.createLineString('');
	lineStringPlacemark.setGeometry(me.lineString);
	me.lineString.setTessellate(true);
	me.drawPolygon();
	ge.getFeatures().appendChild(lineStringPlacemark);
	lineStringPlacemark.setStyleSelector(ge.createStyle(''));
	me.lineStyle = lineStringPlacemark.getStyleSelector().getLineStyle();
	
	google.earth.addEventListener(ge.getGlobe(), "mousemove", function(event) { me.movePMLoc(event); });
	google.earth.addEventListener(ge.getGlobe(), "mousedown", function(event) { me.completelyNewLoc(event); });
}
Polygon.prototype.setBearDist = function() 
{
	this.bear = tt.map.bearing(this.cent.lat,this.cent.lon, this.rad.lat, this.rad.lon);
	this.dist = tt.map.distance(this.cent.lat,this.cent.lon, this.rad.lat, this.rad.lon);
	//Usage:
	//$('#radius').innerHTML = this.dist.toPrecision(6).toString()+' km';
	//$('#bearing').innerHTML = this.bear.toDeg().toPrecision(5).toString()+' deg';
}
Polygon.prototype.setRad = function() 
{
	var latlon = tt.map.destination(this.cent.lat,this.cent.lon, this.dist,this.bear);
	this.rad.setLoc (latlon[0],latlon[1]);
}
Polygon.prototype.colour = function(col) 
{
	this.lineStyle.getColor().set(col);
}
Polygon.prototype.drawPolygon = function() 
{    
	// Draw our Polygon
	var latlon;
	var coords = "";
	this.lineString.getCoordinates().clear();
	for (i=0; i <=this.numsides; i++) 
	{
		latlon = tt.map.destination(this.cent.lat,this.cent.lon,this.dist,this.bear+i*2*pi/this.numsides);
		this.lineString.getCoordinates().pushLatLngAlt(latlon[0],latlon[1],0);
		coords += latlon[1] + "," + latlon[0] + ',0 ';
	}

	this.coverage = this.cent.lat.toDeg().toPrecision(7).toString()+','
	+ this.cent.lon.toDeg().toPrecision(7).toString() + ':'
	+ this.dist.toPrecision(4).toString()+'km ';
	
	this.coords = coords;
	
	tt.cg.polygon = this;
	
	//this.areaCircum();
}
Polygon.prototype.movePMLoc = function(kmlEvent)
{
	if (!this.rad.active && !this.cent.active) 
	{	
		this.colour('ffffffff');
	}
	else 
	{
		 kmlEvent.preventDefault();
		 this.colour('ffc0c0c0');
		 if (this.rad.active) 
		 {
			   this.rad.setLoc (kmlEvent.getLatitude(),kmlEvent.getLongitude());
			   this.setBearDist();
			   this.drawPolygon();
		 }
		 else  // only pick up centre placemark if vertex placemark not selected
		 {    
			   this.cent.setLoc (kmlEvent.getLatitude(),kmlEvent.getLongitude());
			   this.setRad();
			   this.drawPolygon();
		 }
	}
}

Polygon.prototype.completelyNewLoc = function(kmlEvent) 
{

	if(kmlEvent.getAltKey())
	{
		this.cent.active = false;
		this.rad.active = true;
		this.cent.setLoc(kmlEvent.getLatitude(),kmlEvent.getLongitude());
		this.rad.setLoc(kmlEvent.getLatitude(),kmlEvent.getLongitude());
		this.colour('ffc0c0c0');
	}
}
Polygon.prototype.areaCircum = function() 
{   
	// compute area and circumference of Polygon
	var area = 0;
	var circum = 0;
	var latlon;
	if (this.numsides == 25)
	{     
		// area of spherical circle = 2*pi*R^2*(1-cos(radius))
	 	area = 2*pi*6371*6371*(1-Math.cos(this.dist/6371));
	 	circum = 2*pi*6371*(Math.sin(this.dist/6371));
	}
	else if(this.numsides != 2)
	{ 
		// Spherical Polygon of n sides, theta is sum of internal angles: area = (theta-(n-2)*pi)*R^2
 		var latlon = tt.map.destinationr(0,0,this.dist,pi);
 		var latlon2 = tt.map.destinationr(0,0,this.dist,pi-2*pi/this.numsides);
 		var ang = 2*tt.map.bearing(latlon[0],latlon[1],latlon2[0],latlon2[1]);
 		area = ((this.numsides*ang)-(this.numsides-2)*pi)*6371*6371;
 		circum = this.numsides*tt.map.distance(latlon[0],latlon[1],latlon2[0],latlon2[1]);
	}
	//Usage:
	//$('#perim').innerHTML = circum.toPrecision(6).toString()+' km';
	//$('#area').innerHTML = area.toPrecision(8).toString()+' km<sup>2</sup>';

}

/*
 * 
 * 
 * 
 */

//Placemark PM class
function PM(lat,lon,name,colour)   // Create 
{    
	var me = this;
	me.active = false;
	me.name = name;
	me.placemark = ge.createPlacemark('');
	ge.getFeatures().appendChild(me.placemark);
	me.point = ge.createPoint('');
	me.placemark.setStyleSelector(ge.createStyle(''));
	var IconStyle = me.placemark.getStyleSelector().getIconStyle();
	IconStyle.getIcon().setHref("http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png");
	IconStyle.getColor().set(colour);
	IconStyle.setScale(0.5); 
	IconStyle.getHotSpot().setXUnits(ge.UNITS_FRACTION);
	IconStyle.getHotSpot().setYUnits(ge.UNITS_FRACTION);
	IconStyle.getHotSpot().setX(0.5);
	IconStyle.getHotSpot().setY(0.5);
	me.setLoc(lat,lon);
	
	me.placemark.setGeometry(me.point);
	google.earth.addEventListener(me.placemark, "mousedown", function(event) { me.draw(event); });
	google.earth.addEventListener(me.placemark, "mouseup", function(event) { me.undraw(event); });
	
	google.earth.addEventListener(ge.getGlobe(), "mousemove", function(event) { me.movePointLoc(event); });
}
PM.prototype.setLoc = function(lat,lon)  // set location of placemark.
{   
	this.lat = lat.toRad();
	this.lon = lon.toRad();
	this.point.setLatLng(lat,lon.fixLon());
	this.coords = lon.toString() + "," + lat.toString() + ",0";
	//$(this.name).innerHTML = lat.toPrecision(7).toString()+' , '+lon.toPrecision(7).toString();
}
PM.prototype.movePointLoc = function(kmlEvent) 
{	 
	 if (this.active) 
	 {
		 kmlEvent.preventDefault();
		 this.setLoc (kmlEvent.getLatitude(),kmlEvent.getLongitude());

//console.log("editmode",tt.feature.EditModeOn());	
		 if((tt.feature.FeatureMode() === "line"
			|| tt.feature.FeatureMode() === "poly") && (!tt.feature.EditModeOn()))
		 {
//console.log("draw from movePoint");			 
			 tt.feature.DrawFeatures(true);
		 }
	 }
}
PM.prototype.draw = function() 
{
	//mousedown
	this.active = true;
}
PM.prototype.undraw = function(event) 
{
	//mouseup
	this.active = false;
	//launch remove if in edit mode
	
	if(tt.feature.EditModeOn())
	{
		tt.feature.RemovePointFromFeature(this);
		tt.cg.catchDelete = true;
		//I cannot seem to stop this mouseup from firing at window level...
		//event.cancelBubble = true;
		//if (event.stopPropagation) event.stopPropagation();
	}
	
}



/*
 * 
 * Miscellaneous Map functions
 */



function setStyle(placemark)
{
	placemark.setStyleSelector(ge.createStyle(''));
	var IconStyle = placemark.getStyleSelector().getIconStyle();
	IconStyle.getIcon().setHref("http://maps.google.com/mapfiles/kml/shapes/shaded_dot.png");
	IconStyle.getColor().set('ff00ffff'); //yellow
	IconStyle.getHotSpot().setXUnits(ge.UNITS_FRACTION);
	IconStyle.getHotSpot().setYUnits(ge.UNITS_FRACTION);
	IconStyle.getHotSpot().setX(0.5);
	IconStyle.getHotSpot().setY(0.5);
	
	var lineStyle = placemark.getStyleSelector().getLineStyle();
	lineStyle.setWidth(3);
	lineStyle.getColor().set('dd00ffff');  // aabbggrr formatx
	//lineStyle.setColorMode(ge.COLOR_RANDOM);	
	
	var polyStyle = placemark.getStyleSelector().getPolyStyle();
	polyStyle.getColor().set('aa00ffff');  // aabbggrr format
	//polyStyle.setColorMode(ge.COLOR_RANDOM);	
}


function drawContinuousLine(event) //onmousemove
{
	if (current.isMouseDown) 
	{		
		tt.cg.coordset.pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
	}
}

function startAndStopContinuousLine(event) //onmousedown
{
	if (tt.cg.isMouseDown) //user is stopping
	{
		tt.cg.isMouseDown = false;
		tt.cg.coordset.pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
		
		if(tt.feature.FeatureMode() === "poly")
		{
			convertLineStringToPolygon(tt.cg.line);
		}
	} 
	else //user is starting - make it
	{
		tt.cg.isMouseDown = true;
 
		var thisPlacemark = ge.createPlacemark('');
		//var lineString = ge.createLineString('');
		tt.cg.line = ge.createLineString('');
		thisPlacemark.setGeometry(tt.cg.line);
		tt.cg.line.setTessellate(true);
		tt.cg.line.setAltitudeMode(ge.ALTITUDE_CLAMP_TO_GROUND);
 
		thisPlacemark.setStyleSelector(ge.createStyle(''));
		var lineStyle = thisPlacemark.getStyleSelector().getLineStyle();
		lineStyle.setWidth(4);
		lineStyle.getColor().set('ddffffff');  // aabbggrr formatx
		lineStyle.setColorMode(ge.COLOR_RANDOM);
		var polyStyle = thisPlacemark.getStyleSelector().getPolyStyle();
		polyStyle.getColor().set('ddffffff');  // aabbggrr format
		polyStyle.setColorMode(ge.COLOR_RANDOM);
 
		tt.cg.coordset = tt.cg.line.getCoordinates();
		tt.cg.coordset.pushLatLngAlt(event.getLatitude(), event.getLongitude(), 0);
 
		ge.getFeatures().appendChild(thisPlacemark);
	}
}
function convertLineStringToPolygon(placemark) 
{
	var polygon = ge.createPolygon('');
	var outer = ge.createLinearRing('');
	polygon.setOuterBoundary(outer);
 
	var lineString = placemark.getGeometry();
	for (var i = 0; i < lineString.getCoordinates().getLength(); i++) 
	{
		var coord = lineString.getCoordinates().get(i);
		outer.getCoordinates().pushLatLngAlt(coord.getLatitude(), 
                                         coord.getLongitude(), 
                                         coord.getAltitude());
	}
 
	placemark.setGeometry(polygon);
}


/*
 * 
 * Extensions to math
 * 
 */


var pi = Math.PI;

Number.prototype.toRad = function() 
{  
	// convert degrees to radians
	return this * pi / 180;
}
Number.prototype.toDeg = function() 
{  
	// convert radians to degrees
	return this * 180 / pi;
}
Number.prototype.fixLon = function() 
{  
	// keep longitude in range -180 to 180
	lon = this;
	while (lon < -180) {lon +=360;}
	while (lon > 180) {lon -=360;}
	return parseFloat(lon);
}



/*
 * singleton for utility mapping functions
 * 
 * 
 */

tt.map = (function()
{
	//private methods in closure

	
	function setGeLayer(layerConstant, show)
	{
		ge.getLayerRoot().enableLayerById(layerConstant, show);
		
	}
	
	function setGrid(show)
	{
		ge.getOptions().setGridVisibility(show); 
	}
	
	function setNavVisibility(show)
	{
		ge.getNavigationControl().setVisibility(show); 
	}
	
	function setNetworkLink(kmlName)
	{	
tt.makeBalloon.DisplayBalloon("","Wait");
		//var linkPath = tt.cg.mapimg + kmlName;

//alert(kmlName);
		var linkPath = kmlName;
		var networkLink = ge.createNetworkLink("");  
		var link = ge.createLink("");
		link.setHref(linkPath);
		networkLink.setFlyToView(true);
		networkLink.setLink(link);
		ge.getFeatures().appendChild(networkLink);
		ge.setBalloon(null); //erase timesail
tt.makeBalloon.Close();		
	}
	
	//NOTE: not used
	function setNetworkLinks()
	{
		
		//append returned matching features

		for(i = 0; i < tt.cg.requestedKML.kmlList.length; i++)
		{
			
			var linkData = tt.cg.requestedKML.kmlList[i];
			var linkPath = tt.cg.mapimg + linkData[0];
			var linkKeywords = linkData[1];
			
			//alert(linkPath + " " + linkKeywords);
		
			//set the themeList to loaded
			tt.cg.themeList[linkKeywords].loaded = true;
			
			var networkLink = ge.createNetworkLink("");
			networkLink.setFlyToView(true);  
			var link = ge.createLink("");
			link.setHref(linkPath);
			networkLink.setLink(link);
			ge.getFeatures().appendChild(networkLink);

		}	
	}
	
	function getDistance (lata,lona,latb,lonb) 
	{  
		// great circle distance (km)
		return Math.acos(Math.sin(lata)*Math.sin(latb)
		+ Math.cos(lata)*Math.cos(latb)*Math.cos(lonb-lona))*6371;
	}
	
	function getBearing (lata,lona,latb,lonb)
	{
		// initial great circle bearing
		return Math.atan2(Math.sin(lonb-lona)*Math.cos(latb), 
			Math.cos(lata)*Math.sin(latb) -
			Math.sin(lata)*Math.cos(latb)*Math.cos(lonb-lona));
	}
	
	function getDestination (lata,lona,dist,brng) 
	{
		// destination along great circle.  returns values in degrees
		var latb = Math.asin(Math.sin(lata)*Math.cos(dist/6371) + 
			Math.cos(lata)*Math.sin(dist/6371)*Math.cos(brng));
		var lonb = lona+Math.atan2(Math.sin(brng)
			* Math.sin(dist/6371)*Math.cos(lata), 
				Math.cos(dist/6371)-Math.sin(lata)*Math.sin(latb));
				
		return [180*latb/pi, 180*lonb/pi];	
	}
	
	function getDestinationr(lata,lona,dist,brng)
	{
		// destination along great circle.  returns value in radians
		var latb = Math.asin(Math.sin(lata)*Math.cos(dist/6371) + 
			Math.cos(lata)*Math.sin(dist/6371)*Math.cos(brng));
		var lonb = lona+Math.atan2(Math.sin(brng)
			* Math.sin(dist/6371)*Math.cos(lata), 
			Math.cos(dist/6371)-Math.sin(lata)*Math.sin(latb));
			
		return [latb, lonb];
	}
	
	//public methods
	return {	
		distance : function (lata,lona,latb,lonb) 
			{ return getDistance(lata,lona,latb,lonb); },
		bearing : function (lata,lona,latb,lonb) 
			{ return getBearing(lata,lona,latb,lonb); },
		destination : function (lata,lona,dist,brng) 
			{ return getDestination(lata,lona,dist,brng); }, 
		destinationr : function (lata,lona,dist,brng) 
			{ return getDestinationr(lata,lona,dist,brng) ; },		
		SetGeLayer : function(layerConstant, show) {setGeLayer(layerConstant, show);},
		SetGrid : function(show) {setGrid(show);},
		SetNetworkLink : function(kmlName) {setNetworkLink(kmlName);},
		SetNavVisibility : function(show) { setNavVisibility(show);}
		
	};

})();



/*
 * 
 * Examples for making GE Viewer Overlay buttons
 * 
 */


/**
 * Helper function for element.addEventListener/attachEvent
 */
function addDomListener(element, eventName, listener) {
  if (element.addEventListener)
    element.addEventListener(eventName, listener, false);
  else if (element.attachEvent)
    element.attachEvent('on' + eventName, listener);
}


/**
 * Helper function to get the rectangle for the given HTML element.
 */
function getElementRect(element) {
  var left = element.offsetLeft;
  var top = element.offsetTop;

  var p = element.offsetParent;
  while (p && p != document.body.parentNode) {
    if (isFinite(p.offsetLeft) && isFinite(p.offsetTop)) {
      left += p.offsetLeft;
      top += p.offsetTop;
    }

    p = p.offsetParent;
  }

  return { left: left, top: top,
           width: element.offsetWidth, height: element.offsetHeight };
}

/**
 * Create a custom button using the IFRAME shim and CSS sprite technique
 * at the given x, y offset from the top left of the plugin container.
 */
function createNativeHTMLButton(x, y, width, height) {
  // create the button
  var button = document.createElement('a');
  button.href = '#';
  button.className = 'tri-button';
  button.style.display = 'block';
  button.style.backgroundImage = 'url(' + tt.cg.appimg + 'TT_IMG_Logo.png)';
  //button.style.backgroundImage = 'url("http://interface.eyecon.ro/demos/images/bar/display.png")';
  
//alert(button.style.backgroundImage);
  // create an IFRAME shim for the button
  var iframeShim = document.createElement('iframe');
  iframeShim.frameBorder = 0;
  iframeShim.scrolling = 'no';
  iframeShim.src = (navigator.userAgent.indexOf('MSIE 6') >= 0) ?
      '' : 'javascript:void(0);';

  // position the button and IFRAME shim
  var pluginRect = getElementRect(document.getElementById('map3d'));
  button.style.position = iframeShim.style.position = 'absolute';
  button.style.left = iframeShim.style.left = (pluginRect.left + x) + 'px';
  button.style.top = iframeShim.style.top = (pluginRect.top + y) + 'px';
  button.style.width = iframeShim.style.width = width + 'px';
  button.style.height = iframeShim.style.height = height + 'px';

  // set up z-orders
  button.style.zIndex = 10;
  iframeShim.style.zIndex = button.style.zIndex - 1;

  // set up click handler
  addDomListener(button, 'click', function(evt) {

	  window.location="http://timetrail.com/";

    if (evt.preventDefault) {
      evt.preventDefault();
      evt.stopPropagation();
    }
    return false;
  });

  // add the iframe shim and button
  document.body.appendChild(button);
  document.body.appendChild(iframeShim);
}

/**
 * Create a custom button using screen overlays
 * at the given x, y offset from the top left of the plugin container.
 */
function createScreenOverlayButton(url,x, y, width, height, func) {
  var _addOverlayForState = function(suffix, drawOrder, visible) {
    // Create the loading overlay.
    var icon = ge.createIcon('');
   //icon.setHref("images/new/TT_IMG_Logo.PNG"); 
   //icon.setHref("http://"+location.host+'/TimeTrails/images/TT_IMG_Logo.PNG');
   icon.setHref(url);
//    icon.setHref("http://interface.eyecon.ro/demos/images/bar/display.png");
//alert(location.host+'/TimeTrails/images/TT_IMG_Logo.PNG');
    var overlay = ge.createScreenOverlay('');
    overlay.setDrawOrder(drawOrder || 0);
    overlay.setVisibility(visible || false);
    overlay.setIcon(icon);
    overlay.getOverlayXY().set(x, ge.UNITS_PIXELS, y, ge.UNITS_INSET_PIXELS);
    overlay.getScreenXY().set(0, ge.UNITS_FRACTION, 1, ge.UNITS_FRACTION);
    overlay.getSize().set(width, ge.UNITS_PIXELS, height, ge.UNITS_PIXELS);
    ge.getFeatures().appendChild(overlay);

    return overlay;
  };

  var overlayReg = _addOverlayForState('', 1, true);
  var overlayHover = _addOverlayForState('_hover', 2, false);
  var overlayDown = _addOverlayForState('_down', 3, false);

  var _setState = function(state) {
    overlayHover.setVisibility(state == 'hover');
    overlayDown.setVisibility(state == 'down');
  };

  // NOTE: if you have many screen overlay controls, you should collapse
  // this code down to one listener per event to handle all controls.

  var _isMouseOnButton = function(mx, my) {
    return x <= mx && mx <= x + width &&
           y <= my && my <= y + height;
  };

  var buttonDown = false;

  google.earth.addEventListener(ge.getWindow(), 'mousedown', function(evt) {
    if (evt.getButton() != 0) // left click
      return;

    if (_isMouseOnButton(evt.getClientX(), evt.getClientY())) {
      buttonDown = true;
      //_setState('down');
      event.preventDefault();
      return false;
    }
  });

  google.earth.addEventListener(ge.getWindow(), 'mousemove', function(evt) {
    if (_isMouseOnButton(evt.getClientX(), evt.getClientY())) {
      //_setState(buttonDown ? 'down' : 'hover');
    } else {
      //_setState(buttonDown ? 'hover' : '');
    }

    if (buttonDown) {
      event.preventDefault();
      return false;
    }
  });

  google.earth.addEventListener(ge.getWindow(), 'mouseup', function(evt) {
    if (buttonDown) {
      buttonDown = false;
      //_setState(_isMouseOnButton(evt.getClientX(), evt.getClientY()) ?  'hover' : '');
      event.preventDefault();
      return false;
    }
  });

  google.earth.addEventListener(ge.getWindow(), 'click', function(evt) {
	  
	  if (evt.getButton() === 0 &&
        _isMouseOnButton(evt.getClientX(), evt.getClientY())) {
        	
    	buttonDown = false;
    }
  });
}

 
 /***
 *  Milktruck Related
 *
 **/
 
function el(e) { return document.getElementById(e); }
 
function submitLocation() {
  doGeocode(el('address').value);
}

function doGeocode(address) {
  geocoder.getLatLng(address, function(point) {
    if (point) {
      if (ge != null && truck != null) {
        truck.teleportTo(point.y, point.x);
      }
    }
  });
}
 
function addGroundOverlayKml(){
	
var id = "test01";
var href = tt.cg.modimg + "Overlay2.png";
var north = 38.66236496131491;
var south = 38.57328496253496;
var east = -90.1747595658555;
var west = -90.22882019996932;
var rotation = -0.3695820695979188;
var ol = [];

ol.push("<GroundOverlay id='" + id + "'>");	
ol.push("<Icon>");
ol.push("<href>" + href + "</href>");
ol.push("</Icon>");
ol.push("<altitude>0</altitude>");   
ol.push("<altitudeMode>clampToGround</altitudeMode>");
ol.push("<LatLonBox>");
ol.push("<north>" + north + "</north>");                      
ol.push("<south>" + south + "</south>");                    
ol.push("<east>" + east + "</east>");                       
ol.push("<west>" + west + "</west>");                       
ol.push("<rotation>" + rotation + "</rotation>");                 
ol.push("</LatLonBox>");
ol.push("</GroundOverlay>");

return ol.join("");

}

function addScreenOverlayKml(){

var id = "test01";
var sizeX = -1;
var sizeY = -1;
var rotation = 0;	
	
var ol = [];

ol.push("<ScreenOverlay id='" + id + "'>");
ol.push("<name>Test</name>");
ol.push("<description></description>");
ol.push("<Icon>");
ol.push("<href>" + href + "</href>");
ol.push("</Icon>");
ol.push("<overlayXY x='0.5' y='0.5' xunits='fraction' yunits='fraction'/>");
ol.push("<screenXY x='0.5' y='0.5' xunits='fraction' yunits='fraction'/>");
ol.push("<rotation>" + rotation + "</rotation>");
ol.push("<size x='" + sizeX + "' y='" + sizeY + "' xunits='pixels' yunits='pixels'/>");
ol.push("</ScreenOverlay>");

return ol.join("");
}


function flyToLocation(xLon,yLat,zAlt){
	var lookAt = ge.createLookAt(''); 
    lookAt.set(yLat, xLon, 0, ge.ALTITUDE_RELATIVE_TO_GROUND,  0, 0, zAlt); 
    //lookAt.set(point.y, point.x, 10, ge.ALTITUDE_RELATIVE_TO_GROUND,  0, 0, 5000); 
    ge.getView().setAbstractView(lookAt); 
}
 
