// Sine/Cosine Vector Componets (c) Joby Bednar 2009
// All rights reserved
angToRad = function(a){
	return a*(Math.PI/180.0);
};

var sineVector = function(parent, side){
	this.func = function(a){
		var ang = eval(this.angle);
		var scal = eval(this.scale);
		return (0-scal) * Math.sin(angToRad(ang));
	};
	this.angle = 'a';
	this.scale = '100';
	this.active = true;
	this.deleteThis = false;
	//DOM
	this.domObj = $('<div class="vectorBit"><strong>'+side.toUpperCase()+' += scale * SIN(angle&deg;)</strong><br/><label>Scale:</label><input class="scale" value="'+this.scale+'"> <a href="#" onclick="updateScale(this);" class="refresh">«</a><br/><label>Angle:</label><input class="angle" value="'+this.angle+'"> <a href="#" onclick="updateAngle(this);" class="refresh">«</a><br/><input type="checkbox" value="1" class="active" checked="checked" onclick="updateActive(this);" /> Active</div>');
	$('<span class="delete"><a href="#" onclick="deleteVector(this)">✖</a></span>').prependTo(this.domObj);
	this.domObj.data('object', this);
	this.domObj.data('parent', parent);
	var dom = $(parent.domObj).children('span.vector_'+side).children('div.vectorList');
	this.domObj.appendTo(dom);
};

var cosineVector = function(parent, side){
	this.func = function(a){
		var ang = eval(this.angle);
		var scal = eval(this.scale);
		return scal * Math.cos(angToRad(ang));
	};
	this.angle = 'a';
	this.scale = '100';
	this.active = true;
	this.deleteThis = false;
	//DOM
	this.domObj = $('<div class="vectorBit"><strong>'+side.toUpperCase()+' += scale * COS(angle&deg;)</strong><br/><label>Scale:</label><input class="scale" value="'+this.scale+'"> <a href="#" onclick="updateScale(this);" class="refresh">«</a><br/><label>Angle:</label><input class="angle" value="'+this.angle+'"> <a href="#" onclick="updateAngle(this);" class="refresh">«</a><br/><input type="checkbox" value="1" class="active" checked="checked" onclick="updateActive(this);" /> Active</div>');
	$('<span class="delete"><a href="#" onclick="deleteVector(this)">✖</a></span>').prependTo(this.domObj);
	this.domObj.data('object', this);
	this.domObj.data('parent', parent);
	var dom = $(parent.domObj).children('span.vector_'+side).children('div.vectorList');
	this.domObj.appendTo(dom);
};

var offsetVector = function(parent, side){
	this.func = function(a){
		var scal = eval(this.scale);
		return scal;
	};
	this.scale = '20';
	this.active = true;
	this.deleteThis = false;
	//DOM
	this.domObj = $('<div class="vectorBit"><strong>'+side.toUpperCase()+' += amount</strong><br/><label>Amount:</label><input class="scale" value="'+this.scale+'"> <a href="#" onclick="updateScale(this);" class="refresh">«</a><br/><input type="checkbox" value="1" class="active" checked="checked" onclick="updateActive(this);" /> Active</div>');
	$('<span class="delete"><a href="#" onclick="deleteVector(this)">✖</a></span>').prependTo(this.domObj);
	this.domObj.data('object', this);
	this.domObj.data('parent', parent);
	var dom = $(parent.domObj).children('span.vector_'+side).children('div.vectorList');
	this.domObj.appendTo(dom);
};

var addSine = function(side, obj){
	var vector = $(obj).parent().parent().data('object');
	vector[side+'Functions'].push(new sineVector(vector, side));
};

var addCosine = function(side, obj){
	var vector = $(obj).parent().parent().data('object');
	vector[side+'Functions'].push(new cosineVector(vector, side));
};

var addOffset = function(side, obj){
	var vector = $(obj).parent().parent().data('object');
	vector[side+'Functions'].push(new offsetVector(vector, side));
};

var updateScale = function(obj){
	var bitObj = $(obj).parent().data('object');
	bitObj.scale = $(bitObj.domObj).children('input.scale').val();
};

var updateAngle = function(obj){
	var bitObj = $(obj).parent().data('object');
	bitObj.angle = $(bitObj.domObj).children('input.angle').val();
};

var updateActive = function(obj){
	var bitObj = $(obj).parent().data('object');
	bitObj.active = obj.checked ? true : false;
};

var deleteVector = function(obj){
	var bitObj = $(obj).parent().parent().data('object');
	$(bitObj.domObj).slideUp(function(){
		bitObj.active = false;
		bitObj.deleteThis = true;
		$(bitObj.domObj).remove();
	});
};

var deleteObject = function(obj){
	var vObj = $(obj).parent().parent().data('object');
	$(vObj.domObj).slideUp(function(){
		vObj.active = false;
		vObj.deleteThis = true;
		$(vObj.domObj).remove();
		if($('#objs').html()=="") $('#objs').html('(add an object)');
	});
};

var vectorObject = function(imgurl){
	this.ready = false;
	this.active = true;
	this.deleteThis = false;
	this.img = new Image();
	this.img.vObj = this;
	this.img.onload = function(){var obj = this.vObj; obj.ready=true};
	this.img.src = imgurl ? imgurl : 'images/ball.png';
	this.x = 0;
	this.y = 0;
	this.xFunctions = [];
	this.yFunctions = [];
	this.addSine = function(side){
		this[side+'Functions'].push(new sineVector());
	};
	this.addCosine = function(side){
		this[side+'Functions'].push(new cosineVector());
	};
	this.calculateX = function(ang){
		var angle = ang ? ang : '0';
		var obj = this;
		obj.x = 0 - obj.img.width/2;
		for(var i=0; i<obj.xFunctions.length; i++){
			var vector = obj.xFunctions[i];
			if(vector.deleteThis){
				obj.xFunctions.splice(i,1);
				i -= 1;
			} else if(vector.active){
				obj.x += vector.func(angle);
			}
		}
	};
	this.calculateY = function(ang){
		var angle = ang ? ang : '0';
		var obj = this;
		obj.y = 0 - obj.img.height/2;
		for(var i=0; i<obj.yFunctions.length; i++){
			var vector = obj.yFunctions[i];
			if(vector.deleteThis){
				obj.yFunctions.splice(i,1);
				i -= 1;
			} else if(vector.active){
				obj.y += vector.func(angle);
			}
		}
	};
	this.domObj = $('<div class="vectorObject"><img src="'+this.img.src+'"><br/></div>');
	$('<span class="delete"><a href="#" onclick="deleteObject(this);">✖</a></span>').prependTo(this.domObj);
	this.domObj.data('object', this);
	$('<span class="vector_x"><strong>X Vector</strong><br/><a href="#" onclick="addOffset(\'x\', this);">+ offset</a> | <a href="#" onclick="addSine(\'x\', this);">+ sine</a> | <a href="#" onclick="addCosine(\'x\',this);">+ cosine</a> <div class="vectorList"></div></span>').appendTo(this.domObj);
	$('<span class="vector_y"><strong>Y Vector</strong><br/><a href="#" onclick="addOffset(\'y\', this);">+ offset</a> | <a href="#" onclick="addSine(\'y\', this);">+ sine</a> | <a href="#" onclick="addCosine(\'y\',this);">+ cosine</a> <div class="vectorList"></div></span>').appendTo(this.domObj);
	this.domObj.appendTo('#objs');
};

var vcEngine = {
	vars : {
		ready : false,
		offset : {'x':400, 'y':300},
		angle : 0,
		objs : [],
		gfx : {
			screen : null,
			angle : null
		}
	},
	
	addObject : function(url){
		if(this.vars.objs.length==0) $('#objs').html('');
		this.vars.objs.push(new vectorObject(url));
	}, 
	
	tick : function(){
		this.vars.angle = (this.vars.angle+1)%360;
		$('#angle label').html(this.vars.angle);
		for(var i=0; i<this.vars.objs.length; i++){			
			var obj = this.vars.objs[i];
			if(obj.ready && obj.active){
				//calculate all the positions
				obj.calculateX(this.vars.angle);
				obj.x += this.vars.offset.x;
				obj.calculateY(this.vars.angle);
				obj.y += this.vars.offset.y;
			} else if (obj.deleteThis){
				this.vars.objs.splice(i,1);
				i -= 1;
			}
		}
		this.draw();
	},
	
	draw : function(){
		var rendering = $('input[name=rendering]:checked').val();
		
		//angle
		var ang = this.vars.gfx.angle;
		ang.clearRect(0,0,ang.canvas.width,ang.canvas.height);
		ang.beginPath();
		ang.moveTo(10,10);
		ang.lineTo(19,10);
		ang.arc(10,10,9,0,angToRad((-1)*this.vars.angle),true);
		ang.closePath();
		ang.stroke();
		
		//screen
		var sc = this.vars.gfx.screen;
		if(rendering=='t'){
			sc.globalCompositeOperation = 'destination-out';
			sc.fillStyle = 'rgba(0,0,0,0.1)';
			sc.fillRect(0, 0, sc.canvas.width, sc.canvas.height);
		} else if (rendering=='nt'){
			sc.clearRect(0,0,sc.canvas.width,sc.canvas.height);
		}
		sc.globalCompositeOperation = 'source-over';
		
		sc.save();
		//draw objects
		for(var i=0; i<this.vars.objs.length; i++){			
			var obj = this.vars.objs[i];
			if(obj.ready && obj.active){
				sc.drawImage(obj.img, obj.x, obj.y);
			}
		}
		sc.restore();
		//timer
		setTimeout("vcEngine.tick()",20);
	},
	
	init : function(){
		//grfx init
		this.vars.gfx.screen = $('#screen_gfx').get(0).getContext('2d');
		this.vars.gfx.angle = $('#angle_gfx').get(0).getContext('2d');
		//start timer
		setTimeout("vcEngine.tick()",20);
	}
};

$(function(){
	if($.browser.msie){
		$('#iesupport').show();
	} else {
		vcEngine.init();
	}
});
