/*
 * ACCIDENT GALLERY.COM
 *
 * Class: spline.js
 * Version: 1.0.0
 * Desc:	Catmull-Rom Spline used for creating
 * 		time curves in instances of the Tween
 *		class.
 *
 * Preset Curve Values
 *	Ease In-Out (Sinusoidal Hard)
 *		p = [	{x: 0.00,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 0.00,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 0.40,  y: 0.20,  c: 0.50,  m:null},
 *			{x: 0.60,  y: 0.80,  c: 0.50,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 1.00,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 1.00,  m:null}	]
 *	Ease In-Out (Sinusoidal Soft)
 *		p = [	{x: 0.00,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 0.00,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 1.00,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 1.00,  m:null},
 *	Ease In (Exponential)
 *		p = [	{x:-0.10,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 0.00,  y: 0.00,  c: 1.00,  m:null},
 *			{x: 0.33,  y: 0.04,  c: 0.80,  m:null},
 *			{x: 0.66,  y: 0.33,  c: 0.70,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 1.00,  m:null},
 *			{x: 1.10,  y: 1.00,  c: 1.00,  m:null}	]
 *	Ease Out (Logarithmic)
 *		p = [	{x: 0.00,  y: 0.00,  c: 0.20,  m:null},
 *			{x: 0.00,  y: 0.00,  c: 0.20,  m:null},
 *			{x: 0.30,  y: 0.80,  c: 0.80,  m:null},
 *			{x: 0.70,  y: 0.96,  c: 0.70,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 0.70,  m:null},
 *			{x: 1.00,  y: 1.00,  c: 0.70,  m:null}	]
 */

var Spline = function(paramRes, paramList) {
	var res = null;
	var p = [];

	// HERMITE BASIS FUNCTIONS
	function h00(t) {
		var ret = (2 * (t * t * t)) - (3 * (t * t)) + 1;
		return ret;
	}
	function h10(t) {
		var ret = (t * t * t) - (2 * (t * t)) + t;
		return ret;
	}
	function h01(t) {
		var ret = -(2 * (t * t * t)) + (3 * (t * t));
		return ret;
	}
	function h11(t) {
		var ret = (t * t * t) - (t * t)
		return ret;
	}

	function calcTangents() {
		for(var k=1;k<p.length-1;k++) {
			p[k].m = (1 - p[k].c) * ((p[k+1].y - p[k-1].y) / (p[k+1].x - p[k-1].x));
		}
	}
	function calc(j) {
		var pt = null;
		for(var k=1;k<p.length-1;k++) {
			if((j/res) < p[0].x) {
				break;
			}
			/*if((j/res) >= p[k].x && (j/res) < p[k+1].x) {
				pt = k;
				break;
			} else {
				continue;
			}*/

			if(p[k+1].x != p[k].x) {
				if((j/res) >= p[k].x && (j/res) < p[k+1].x) {
					pt = k;
					break;
				} else {
					continue;
				}
			} else {
				if((j/res) == p[k].x && (j/res) == p[k+1].x) {
					pt = k+1;
					break;
				} else {
					continue;
				}
			}
		}
		if(pt != null) {
			var t = (((j+1)/res) - p[pt].x) / (p[pt+1].x - p[pt].x);
			
			var term0 = h00(t) * p[k].y;
			var term1 = h10(t) * p[k].m;
			var term2 = h01(t) * p[k+1].y;
			var term3 = h11(t) * p[k+1].m;
			var retVal = term0 + term1 + term2 + term3;

			/*
			 * CANVAS DEBUGGER

			if(pt == Number(p.length - 3) && t > 0.9) {
				debugDrawPoints();
			} else {
				debugDrawCurve(pt, t, (j / res) * 100, 100 - (retVal * 100));
			}
			
			 * END DEBUGGER
			 */
			return retVal;
		}
	}
	function debugDrawCurve(nPoint, t, xCoord, yCoord) {
		var gfx = document.getElementById("graph");
		var ctx = gfx.getContext("2d");

		if(nPoint == 1 && t == 0) {
			ctx.fillStyle="rgb(127,127,127)";
			ctx.fillRect(0,0,100,100);
			ctx.beginPath();
			ctx.moveTo(xCoord, yCoord);
		} else {
			ctx.lineTo(xCoord, yCoord);
			ctx.stroke();
		}
	}
	function debugDrawPoints() {
		var gfx = document.getElementById("graph");
		var ctx = gfx.getContext("2d");
		for(var dot=0;dot<p.length;dot++) {
			ctx.beginPath();
			ctx.lineStyle="rgba(0,0,0,0)";
			ctx.fillStyle="rgba(255,0,0,0.5)";
			ctx.arc(p[dot].x * 100, 100 - (p[dot].y * 100), 4, 0, 2 * Math.PI, false);
			ctx.closePath();
			ctx.fill();
		}
	}
	function _construct(pRes,pList) {
		res = pRes;
		p = pList;
		calcTangents();
	}
	this._construct = _construct;
	this.calc = calc;

	_construct(paramRes,paramList);
}