Engine.LerpSet = class
{
	get count()
	{
		return this.keyframes.length;
	}

	setOverride(overrideValue /*T*/)
	{
		this.hasOverride = true;
		this.overrideValue = overrideValue;
	}

	clearOverride()
	{
		this.hasOverride = false;
	}

	constructor()
	{
		this.loop = false;
		this.keyframes = [];//new List<T>();
		this.percents = [];//new List<float>();
		this.hasOverride = false;
		this.overrideValue = 0;
		this.defaultValue = this.getDefault();
	}

	add(keyframe /*T*/, percent /*float*/)
	{
		this.keyframes.push(keyframe);

		if (percent === undefined)
		{
			this.percents = [];
			this.percents.push(0);
			var pointSpacing = (this.keyframes.length - 2) > 0 ? 1 / (this.keyframes.length - 1) : 1;
			for (var i = 1; i < this.keyframes.length; i++)
			{
				if (i == this.keyframes.length - 1) break;
				this.percents.push(pointSpacing * i);
			}
			if (this.keyframes.length >= 2) this.percents.push(1);
		}
		else
		{
			this.percents.push(percent);
		}
	}

	get(percent /*float*/)
	{
		
		if (this.hasOverride) return this.overrideValue;
		if (this.percents.length == 0) return this.defaultValue;
		if (this.percents.length == 1) return this.keyframes[0];
		
		if (percent < 0) percent = 0;
		if (percent > 1) percent = this.loop ? percent - Math.floor(percent) : 1;
		
		//find the bounding points
		for (var i = 0; i < this.percents.length; i++)
		{
			//edge case right on the point.
			if (this.percents[i] == percent) return this.keyframes[i];
			
			if (this.percents[i] > percent)
			{
				if (i == 0) return this.keyframes[0];
				
				var innerPercent = (percent - this.percents[i - 1]) / (this.percents[i] - this.percents[i - 1]);
				var left = this.keyframes[i - 1];
				var right = this.keyframes[i];
				
				return this.lerp(left, right, innerPercent);
			}
		}
		
		return this.keyframes[this.keyframes.length - 1];
	}

	getDefault()
	{
		return 0;
	}
}


Engine.FloatLerpSet = class extends Engine.LerpSet
{
	constructor() { super(); }

	lerp(a /*float*/, b /*float*/, percent /*float*/)
	{
		return a * (1.0 - percent) + b * percent;
	}
}

Engine.ColorLerpSet = class extends Engine.LerpSet
{
	
	constructor() { super(); }

	lerp(a /*Color*/, b /*Color*/, percent /*float*/)
	{
		var ret = Engine.Vector3LerpSet.v3Lerp(new Vector3(a.r, a.g, a.b), new Vector3(b.r, b.g, b.b), percent);
		return new Color(ret.x, ret.y, ret.z);
	}
}

Engine.Vector2LerpSet = class extends Engine.LerpSet
{
	constructor() { super(); }

	lerp(a /*Vector2*/, b /*Vector2*/, percent /*float*/)
	{
		var delta = b.clone().sub(a);
		return a.clone().add(delta.multiplyScalar(percent));
	}
}

Engine.Vector3LerpSet = class extends Engine.LerpSet
{
	static v3Lerp(a /*Vector3*/, b /*Vector3*/, percent /*float*/)
	{
		var delta = b.clone().sub(a);
		return a.clone().add(delta.multiplyScalar(percent));
	}

	lerp(a /*Vector3*/, b /*Vector3*/, percent /*float*/)
	{
		return Engine.Vector3LerpSet.v3Lerp(a, b, percent);
	}
}