/*
* All rights reserved.
* copyright (c) 2005 Chris Lacy
*/

function Traveller(colorContainer, maxTrkpts) {

	this.trkName = null;
	this.colorContainer = colorContainer;
	this.icon = IconFactory.createIconFromColorContainer(colorContainer);
	this.maxTrkpts = maxTrkpts;
	this.timeToLatLonArray = [];
	this.timeToLatLonArrayCache = [];
	
	this.maxLat = null;
	this.maxLon = null;
	this.minLat = null;
	this.minLon = null;
	this.maxTime = null;
	this.minTime = null;
	this.centerLatLon = null;
	
	this.oldPositionMarker = null;

	this.waypointLatLonArray = [];
}

Traveller.prototype.getName = function() {
	return this.trkName;
}
	
Traveller.prototype.getMaxLat = function() {
	return this.maxLat;
}

Traveller.prototype.getMaxLon = function() {
	return this.maxLon;
}

Traveller.prototype.getMinLat = function() {
	return this.minLat;
}

Traveller.prototype.getMinLon = function() {
	return this.minLon;
}

Traveller.prototype.getMaxTime = function() {
	return this.maxTime;
}

Traveller.prototype.getMinTime = function() {
	return this.minTime;
}

Traveller.prototype.getCenterLatLon = function() {
	return this.centerLatLon;
}

Traveller.prototype.createWaypointLatLonArray = function(xmlDoc) {
	var wayElements = xmlDoc.getElementsByTagName('wpt');
	for(var i=0; i<wayElements.length; i++) {
		var waylat = parseFloat(wayElements[i].getAttribute('lat'));
		var waylon = parseFloat(wayElements[i].getAttribute('lon'));
		
		this.waypointLatLonArray[i] = new LatLon(waylat, waylon);
	}
};

Traveller.prototype.addWaypoints = function(map) {
	for(var i=0; i<this.waypointLatLonArray.length; i++) {
		map.addOverlay(this.waypointLatLonArray[i].getGMarker());
	}
}

// private - assume time is a number indicating uncorrected time
Traveller.prototype.getLatLonForTime = function(time) {
	var correctedTime = time - this.minTime;
	var latLon = this.timeToLatLonArrayCache[correctedTime];
	if(!latLon) {
		latLon = this.timeToLatLonArray[correctedTime];
		if(latLon) {
			this.timeToLatLonArrayCache[correctedTime] = latLon;
		}
	}
	
	if(!latLon) {
		// undefined tf extrapolate
		var lesserTime = null;
		var lesserLatLon = null;
		var greaterTime = null;
		var greaterLatLon = null;
		
		for(lesserTime=time; lesserLatLon == null && lesserTime>=this.minTime; lesserTime--) {
			lesserLatLon = this.timeToLatLonArray[lesserTime - this.minTime];
		}
		if(!lesserLatLon || lesserLatLon == null) {
			lesserLatLon = this.timeToLatLonArray[0];
		}
		
		for(var greaterTime=time; greaterLatLon == null && greaterTime<=this.maxTime; greaterTime++) {
			greaterLatLon = this.timeToLatLonArray[greaterTime - this.minTime];
		}
		if(!greaterLatLon || greaterLatLon == null) {
			greaterLatLon = this.timeToLatLonArray[this.maxTime - this.minTime];
		}
		
		var timeRatio = (time-lesserTime) / (greaterTime-lesserTime);
		var newLat = ((greaterLatLon.getLat() - lesserLatLon.getLat()) * timeRatio ) + lesserLatLon.getLat();
		var newLon = ((greaterLatLon.getLon() - lesserLatLon.getLon()) * timeRatio ) + lesserLatLon.getLon();
		
		latLon = new LatLon(newLat, newLon);
		
		this.timeToLatLonArrayCache[correctedTime] = latLon;
	}
	
	return latLon;
}

// private - assume time is a number
Traveller.prototype.getGPointForTime = function(time) {

	var latLon = this.getLatLonForTime(time);
	return new GPoint(latLon.getLon(), latLon.getLat());
}

// public - time must be an integer
Traveller.prototype.moveToTrackPoint = function(time, map) {

	if(this.oldPositionMarker) {
		map.removeOverlay(this.oldPositionMarker);
	}
	var newPoint = this.getGPointForTime(time);
	this.oldPositionMarker = new GMarker(newPoint, this.icon);

	map.addOverlay(this.oldPositionMarker);
};

// private
Traveller.prototype.assignCenterLatLon = function(xmlDoc) {
	var lat = (this.maxLat - this.minLat)/2 + this.minLat;
	var lon = (this.maxLon - this.minLon)/2 + this.minLon;
	this.centerLatLon = new LatLon(lat, lon);
}

Traveller.prototype.getGPolyline = function(color) {
	var gPointArray = [];
	var incrementFactor = (this.maxTime - this.minTime) / this.maxTrkpts;

	for(var i=this.minTime; i<=this.maxTime; i += incrementFactor) {
		var time = Math.floor(i);
		var gPoint = this.getGPointForTime(time);
		gPointArray.push(gPoint);
	}
	return new GPolyline(gPointArray, this.colorContainer.getColorHashString(), 2);
}

Traveller.prototype.getGreatestSpanObject = function() {

	var span = new Object();
	span.width = this.getMaxLon() - this.getMinLon();
	span.height = this.getMaxLat() - this.getMinLat();
	return span;
}

Traveller.prototype.willCauseError = function() {
	if(this.waypointLatLonArray.length > 400 || this.timeToLatLonArray.length > 100000) {
		return true;
	}
	return false;
}
		
