var ST = window.ST || {};

//////////////////////////////////////////
//////
//////	
//////
//////////////////////////////////////////

ST.updateSize = function(_canvaswidth,_canvasheight,_trianglesize) {
	ST.width = 2*_canvaswidth;
	ST.height = 2*_canvasheight;

	if(ST.canvas) {
		//	resize canvases
		ST.ctx.clearRect ( 0 , 0 , ST.canvas.width , ST.canvas.height );
		ST.buffer.width = ST.canvas.width = ST.width;
		ST.buffer.height = ST.canvas.height = ST.height;

	}

	//	change triangle sidelength
	ST.CONSTANTS.sidelength = 2*_trianglesize || ST.CONSTANTS.sidelength;
	ST.reset();
};

//	change colors of triangle
//	pass array of hex-colors or rgb-colors
ST.updateColors = function( _colors ) {
	ST.colors = _colors || ST.CONSTANTS.defaultColors;
	ST.setType(ST.BEHAVIOURS[Math.floor(ST.BEHAVIOURS.length*Math.random(0,1))]);
};

//////////////////////////////////////////
//////
//////	OBJECTS
//////
//////////////////////////////////////////

//			TRIANGLE POINT			//

ST.TrianglePoint = function( _x, _y ){
	var self = this;
	self.x = _x;
	self.y = _y;
};

//////////////////////////////////////////
//////////////////////////////////////////
//////////////////////////////////////////
//////////////////////////////////////////
//////////////////////////////////////////
//////////////////////////////////////////

ST.CONSTANTS = {
	sidelength: 176,
	rows: 2,
	angle: -20,
	transition: 12,
	width: 360,
	height: 364,
	defaultColors: ["rgb(20,20,20)","rgb(50,50,50)","rgb(30,30,30)","rgb(40,40,40)","rgb(30,30,30)","rgb(40,40,40)"]
};

//	future triangle behaviour types should be added here
ST.BEHAVIOURS = [
	'grid'
];

ST.colors = [];
ST.points = [];
ST.controller = 0;	// controller handles behaviour of points
ST.currentBehaviour = 0;
ST.canvas = 0;
ST.drawctx = 0;
ST.ctx = 0;
ST.buffer = 0;
ST.initialized = false;

ST.reset = function() {
	ST.currentBehaviour = 0;
	ST.controller = 0;
	ST.createPoints();
};

ST.init = function(){
	if(!Modernizr.canvas || ST.initialized) return;
	ST.initialized = true;

	ST.canvas = document.createElement( 'canvas' );
	ST.drawctx = ST.canvas.getContext( '2d' );

	ST.buffer = document.createElement( 'canvas' );
	ST.ctx = ST.buffer.getContext( '2d' );

	ST.width = ST.buffer.width = ST.canvas.width = ST.width || ST.CONSTANTS.width;
	ST.height = ST.buffer.height = ST.canvas.height = ST.height || ST.CONSTANTS.height;

	var container = document.getElementById( 'triangle' );
	container.appendChild( ST.canvas );

	ST.createPoints();
	ST.update();
};

ST.createPoints = function() {
	//	create points for triangle
	var sl = ST.CONSTANTS.sidelength/ST.CONSTANTS.rows;
	var th = Math.sin(Math.PI/3)*sl;
	var myY = -2/3*(th*ST.CONSTANTS.rows)+7*(ST.width/180);
	var myX = 0;
	ST.points = [];

	for (var i = 0; i < ST.CONSTANTS.rows+1; i++) {
		var numpoints = i+1;
		myX = -i*sl*0.5-1;
		for (var j = 0; j < numpoints; j++) {
			ST.points.push( new ST.TrianglePoint(myX,myY) );
			myX += sl;
		}
		myY += th;
	}

	//	set first behaviour
	ST.setType(ST.BEHAVIOURS[Math.floor(ST.BEHAVIOURS.length*Math.random())]);
};

ST.setType = function( _type ) {

	if(ST.points.length<=0) return;

	if(ST.controller) ST.controller.transition();

	if(ST.currentBehaviour===_type) return;
	switch(_type) {
		case 'grid':
			ST.controller = new ST.GRID.Grid();
			break;
		case 'futurebehaviour':
			break;
		default:
			console.log("ERROR -> Unsupported behaviour (ST.setType())");
	}
	ST.currentBehaviour = _type;
};

ST.update = function() {
	//stats.begin();
	if(ST.controller) {
		ST.controller.update();
		ST.draw();
	}
	//stats.end();
	requestAnimationFrame( ST.update );
};

ST.draw = function() {
	if(!ST.controller) return;

	ST = this;
    ST.ctx.fillStyle = "#EDEDED";
    ST.ctx.fillRect(0,0,ST.width,ST.height );

	ST.ctx.save();
	ST.ctx.translate(ST.width*(0.45), ST.height*0.5);
	ST.ctx.rotate(ST.CONSTANTS.angle * Math.PI / 180);
	ST.controller.draw(ST.ctx);
	ST.ctx.restore();

	ST.drawctx.drawImage(ST.buffer, 0, 0);
};
/*
$(window).load(function(e){ 
	stats = new Stats(); 
	stats.setMode( 0 );
	document.body.appendChild( stats.domElement );

	ST.init(); 
	ST.updateColors(["rgb(140,0,153)","rgb(0,183,207)","rgb(255,182,0)","rgb(255,66,0)"]);
});

$(window).resize(function(){
	var size = Math.round(Math.random()*200+120);
	ST.updateSize(size,size,size*0.5);
});*/
ST.GRID = window.ST.GRID || {};

//		GRIDDLE TRIANGLE BEHAVIOUR		//

ST.GRID.Grid = function(_points){
	var me = this;
	me.points = _points;
	me.triangles = [];
	//	beat defines how many frames one colour cycle lasts
	me.defaultBeat = 1000;
	me.beat = me.defaultBeat;
	me.targetBeat = me.defaultBeat;
	me.currentBeat = 0;
	//	speed 
	me.speed = 1;
	me.targetSpeed = 1;
	//	transition
	me.blinkMax = 1;	// how many times shall we loop before going back to default beat during transition
	me.blinkCount = 0;

	me.setup = function(){
		// create triangles and pass correct points from point grid
		for (var i = 0; i < ST.CONSTANTS.rows; i++) {
			var numTriangles = i*2+1;
			for (var j = 0; j < numTriangles; j++) {
				var p1 = j%2===0 ? (i+1)*(i/2)+(j/2) : (i+1)*(i/2)+((j-1)/2);
				var p2 = j%2===0 ? (i+2)*((i+1)/2)+(j/2) : (i+1)*(i/2)+((j-1)/2)+1;
				var p3 = j%2===0 ? (i+2)*((i+1)/2)+(j/2+1) : (i+2)*((i+1)/2)+((j-1)/2+1);
				var t = new ST.GRID.Triangle("rgb(0,0,0)",ST.points[p1],ST.points[p2],ST.points[p3]);
				me.triangles.push(t);
			}
		}
	};

	me.update = function(){

		//	update progress and speed
		me.currentBeat+=me.speed;
		me.setBeat( me.beat+(me.targetBeat-me.beat)*0.005 );
		var progress = Math.max(0,Math.min(1,me.currentBeat/me.beat));
		me.targetSpeed = (progress>0.65 || progress<0.05) ? 3 : 1;
		me.speed += (me.targetSpeed-me.speed)*0.01;

		//	update triangles
		for (var i = 0; i < me.triangles.length; i++) me.triangles[i].update(progress);

		//	check beat loop
		if(me.currentBeat>=me.beat) {
			// check blink count
			if(me.blinkCount>=me.blinkMax) {
				me.targetBeat = me.defaultBeat;
				me.blinkCount = 0;
			} else me.blinkCount++;
			me.currentBeat = 0;
		}		

	};

	me.draw = function(_ctx) {
		for (var i = 0; i < me.triangles.length; i++) {
			var t = me.triangles[i];
			t.draw(_ctx);
		}
	};

	me.transition = function() {
		me.setBeat(ST.CONSTANTS.transition);
		me.targetBeat = me.beat;
		me.currentBeat = 0;
		me.blinkCount = 0;
		var cid, colorChange=false;
		for (var j = 0; j < me.triangles.length; j++) { 
			var t = me.triangles[j];
			t.setColors(ST.colors); 
			t.show();
			if(cid && t.cid != cid) colorChange = true;
			cid = t.cid; 
		}
		//	check that at least two colors are used and change one triangles color if not
		if(!colorChange) {
			var trandom = me.triangles[Math.floor(Math.random()*me.triangles.length)];
			trandom.show(0,(trandom.cid>=ST.colors.length-1?0:trandom.cid+1));
		}
	};

	//	set new beat and change currentBeat acording to current progress
	me.setBeat = function(_beat) {
		me.currentBeat = Math.round((me.currentBeat/me.beat)*_beat);
		me.beat = _beat;
	};

	me.setup();
};

//			TRIANGLE			//
ST.GRID.Triangle = function( _color, _p1, _p2, _p3 ){

	var me = this;
	me.color = _color;
	me.tpoints = [_p1,_p2,_p3];

	me.sub = 0;
	me.cid = Math.floor(Math.random()*ST.colors.length);

	me.init = function() {
		me.show();
	};

	me.update = function(_progress) {
		me.sub.update(_progress);
		if(_progress>=1) {
			me.color = me.sub.color;
			me.show();
		}
	};

	me.draw = function(_ctx) {
		var p1, p2, p3;
		p1 = me.sub.direction === 2 ? me.sub.p3 : me.tpoints[0];
		p2 = me.sub.direction === 0 ? me.sub.p1 : me.tpoints[1];
		p3 = me.sub.direction === 1 ? me.sub.p2 : me.tpoints[2];

		me.drawTriangle(_ctx,me.color,p1,p2,p3);
		me.drawTriangle(_ctx,me.sub.color,me.sub.p1,me.sub.p2,me.sub.p3);
	};

	me.show = function( _direction, _cid ) {
		var direction = _direction || Math.floor(Math.random()*3);
		me.cid = _cid?_cid:(me.cid>=ST.colors.length-1?0:me.cid+1);
		me.sub =  new ST.GRID.SubTriangle(ST.colors[me.cid],direction,me.tpoints[0],me.tpoints[1],me.tpoints[2]);
	};

	me.drawTriangle = function( _ctx,_color,_p1,_p2,_p3 ) {
		_ctx.beginPath();
		_ctx.moveTo(_p1.x,_p1.y);
		_ctx.lineTo(_p2.x,_p2.y);
		_ctx.lineTo(_p3.x,_p3.y);
		_ctx.fillStyle = _color;
		_ctx.fill();
		_ctx.fill();
	};

	me.setColors = function(_colors) {
		me.cid = Math.floor(Math.random()*ST.colors.length);
	};

	me.init();
};

ST.GRID.SubTriangle = function( _color, _start, _p1, _p2, _p3 ) {
	var me = this;
	me.color = _color;
	me.direction = _start;

	if(_start===0) {
		me.p1 = new ST.TrianglePoint(_p2.x,_p2.y);
		me.p2 = new ST.TrianglePoint(_p2.x,_p2.y);
		me.p3 = new ST.TrianglePoint(_p3.x,_p3.y);
	} else if(_start===1) {
		me.p1 = new ST.TrianglePoint(_p1.x,_p1.y);
		me.p2 = new ST.TrianglePoint(_p3.x,_p3.y);
		me.p3 = new ST.TrianglePoint(_p3.x,_p3.y);
	} else {
		me.p1 = new ST.TrianglePoint(_p1.x,_p1.y);
		me.p2 = new ST.TrianglePoint(_p2.x,_p2.y);
		me.p3 = new ST.TrianglePoint(_p1.x,_p1.y);
	}

	me.s1 = new ST.TrianglePoint(me.p1.x,me.p1.y);
	me.s2 = new ST.TrianglePoint(me.p2.x,me.p2.y);
	me.s3 = new ST.TrianglePoint(me.p3.x,me.p3.y);
	
	me.t1 = _p1;
	me.t2 = _p2;
	me.t3 = _p3;

	me.update = function(_progress) {
		me.p1.x = me.s1.x+(me.t1.x-me.s1.x)*_progress;
		me.p1.y = me.s1.y+(me.t1.y-me.s1.y)*_progress;

		me.p2.x = me.s2.x+(me.t2.x-me.s2.x)*_progress;
		me.p2.y = me.s2.y+(me.t2.y-me.s2.y)*_progress;

		me.p3.x = me.s3.x+(me.t3.x-me.s3.x)*_progress;
		me.p3.y = me.s3.y+(me.t3.y-me.s3.y)*_progress;
	};
};
