var settings = {
	//Main
	tunCanvasId: 'tunnelerCanvas',
	//Background
	pixel1Color: '#be7833',
	pixel2Color: '#b85600',
	pixelSize: 4,
	//Tanks
	tankColors: 50,	//Max 255
	tankHeadColor: 'rgb(255, 255, 0)',
};

var tankSize = {
	x: 15,
	y: 20,
	sideX: 5,
	sideY: 30,
	headX: 5,
	headY: 20,
}

var myDebug;

window.onload = function(){
	var canvas = new MyCanvas(settings);
	
	myDebug = new Debug(canvas);
	
	var drawArea = canvas.drawArea;
	var draw = new Draw(settings, canvas);
	var background = new Background(settings, draw);
	var game = new Game(settings, draw);
	
	background.fill();
	
	var colorPicker = new PickColor(settings.tankColors, function(color){game.createTank(color, 10, 10, true)} );
	game.createTank('#990000', 100, 100, false);
	//game.createTank('#009900', 150, 200, false);
	//game.createTank('#000099', 200, 90, false);
}

/* Canvas object */
function MyCanvas(settings){
	this.element = document.getElementById(settings.tunCanvasId);
	this.drawArea =this.element.getContext('2d');
}

/* Background object */
function Background(settings, draw){
	this.draw = draw;
	
	this.fill = fill;
	function fill(){	//Fill background
		for(var y = 0; y < this.draw.height; y++){
			for(var x = 0; x < this.draw.width; x++){
				var offsetX = settings.pixelSize * x;
				var offsetY = settings.pixelSize * y;
				
				if( rand(0, this.draw.height) % 2 == 0 )	//Random generator
					this.draw.pixel(settings.pixel1Color, offsetX, offsetY);
				else
					this.draw.pixel(settings.pixel2Color, offsetX, offsetY);
			}
		}
		
	}
}

/* Draw object */
function Draw(settings, canvas){
	this.drawArea = canvas.drawArea;
	this.width = canvas.element.width;
	this.height = canvas.element.height;
	
	this.pixel = pixel;
	function pixel(color, x, y){
		this.rectangle(color, x, y, 0, 0, settings.pixelSize, settings.pixelSize);
	}
	
	this.rectangle = rectangle;
	function rectangle(color, begX, begY, offsetX, offsetY, width, height, rotation){
		rotation = typeof rotation !== 'undefined' ? rotation : 0;
		
		begX = roundCoord(begX);
		begY = roundCoord(begY);
		offsetX = roundCoord(offsetX);
		offsetY = roundCoord(offsetY);
		
		this.drawArea.fillStyle = color;
		
		this.drawArea.save();
		this.drawArea.translate( begX, begY );
		
		if( rotation != 0 )
			this.rotate(rotation);
			
		this.drawArea.fillRect( offsetX, offsetY, width, height );
		
		this.drawArea.restore();
	}
	
	this.drawTank = drawTank;
	function drawTank(color, rect, erase){
		erase = typeof erase !== 'undefined' ? erase : false;
		
		var darkerColor;
		var tankHeadColor;
		if( erase ){
			darkerColor = color;
			tankHeadColor = color;
		} else {
			darkerColor = changeColor(color, 0.5);
			tankHeadColor = settings.tankHeadColor;
		}
				
		//Body
		var bodyOffset = new Rectangle(
				-0.5 * tankSize.x, 
				-0.5 * tankSize.y, 
				tankSize.x, 
				tankSize.y
		);
		//Left side
		var lSideOffset = new Rectangle(
				bodyOffset.x - tankSize.sideX, 
				-0.5 * tankSize.sideY, 
				tankSize.sideX, 
				tankSize.sideY
		);
		//Right side
		var rSideOffset = new Rectangle(
				bodyOffset.getX2(), 
				-0.5 * tankSize.sideY, 
				tankSize.sideX, 
				tankSize.sideY
		);
		//Head
		var headOffset = new Rectangle(
				-0.5 * tankSize.headX, 
				0, 
				tankSize.headX, 
				tankSize.headY
		);
		
		if( rect.isDummy() ){
			var newCenter = getCenterOfRectangle(rect.x, rect.y, tankSize.x, tankSize.y);
			rect.x = newCenter['x'] + lSideOffset.x;		
			rect.y = newCenter['y'] + lSideOffset.y;
			rect.setCenter( newCenter['x'], newCenter['y']);
		}
		
		var center = rect.getCenter();

		rect.width = lSideOffset.width + bodyOffset.width + rSideOffset.width;
		rect.height = lSideOffset.height;
		
		//center = rect.getCenter();
		
		this.rectangle( color, center['x'], center['y'], bodyOffset.x, bodyOffset.y, bodyOffset.width, bodyOffset.height, rect.rotation);
		this.rectangle( darkerColor, center['x'], center['y'], lSideOffset.x, lSideOffset.y, lSideOffset.width, lSideOffset.height, rect.rotation);
		this.rectangle( darkerColor, center['x'], center['y'], rSideOffset.x, rSideOffset.y, rSideOffset.width, rSideOffset.height, rect.rotation);
		this.rectangle( tankHeadColor, center['x'], center['y'], headOffset.x, headOffset.y, headOffset.width, headOffset.height, rect.rotation);
		
		
		/*var myRect = new Rectangle(
			center['x'] + lSideOffset.x, 
			center['y'] + lSideOffset.y,
			lSideOffset.width + bodyOffset.width + rSideOffset.width,
			lSideOffset.height,
			rotation
		);
		
		myRect.setCenter(center['x'], center['y']);
		return myRect;*/
		//this.rectangle( '#ff0000', x, y,0, 0, 5,5,0);
		//this.rectangle( '#ff0000', x, y+tankSize.y,0, 0, 5,5,0);
		//this.rectangle( '#ff0000', x, y+tankSize.y,0, 0, tankSize.x,1,0);
	}
	
	this.eraseTank = eraseTank;
	function eraseTank(rect){
		this.drawTank('rgb(0,0,0)', rect, true);
	}
	
	this.rotate = rotate;
	function rotate(deg){
		this.drawArea.rotate( degToRad(deg) );
	}
	
	this.getPixels = getPixels;
	function getPixels(x, y, width, height){
		return this.drawArea.getImageData(x, y, width, height);
	}
}

/* Rectangle object */
function Rectangle(x, y, width, height, rotation){
	rotation = typeof rotation !== 'undefined' ? rotation : 0;
	
	this.x = x;
	this.y = y;
	this.width = width;
	this.height = height;
	
	this.rotation = rotation;
	
	this.centerXOffset = 0;
	this.centerYOffset = 0;
	
	this.getX2 = getX2;	
	function getX2(){
		return this.x + this.width;
	}
	
	this.getY2 = getY2;	
	function getY2(){
		return this.y + this.height;
	}
	
	this.getRealCoords = getRealCoords;
	function getRealCoords(){
		var points = new Array();
		
		var center = getCenterOfRectangle( this.x, this.y, this.width, this.height );
		points[0] = rotatePointAround( this.x, this.y, center['x'], center['y'], this.rotation );
		points[1] = rotatePointAround( this.getX2() , this.y, center['x'], center['y'], this.rotation );
		points[2] = rotatePointAround( this.x, this.getY2(), center['x'], center['y'], this.rotation );
		points[3] = rotatePointAround( this.getX2(), this.getY2(), center['x'], center['y'], this.rotation );
		
		return points;
	}
	
	this.setCenter = setCenter;
	function setCenter(x, y){
		this.centerXOffset = x - this.x;
		this.centerYOffset = y - this.y;
	}
	
	this.getCenter = getCenter;	
	function getCenter(){
		var center = new Array();
		center['x'] = this.x + this.centerXOffset;
		center['y'] = this.y + this.centerYOffset;
		
		return center;
	}
	
	this.isDummy = isDummy;	
	function isDummy(){
		if( this.width == 0 && this.height == 0)
			return true;
		return false;
	}
	
	this.copy = copy;
	function copy(rectTo){
		rectTo.x = this.x;
		rectTo.y = this.y;
		
		rectTo.width = this.width;
		rectTo.height = this.height;
		rectTo.rotation = this.rotation;
		
		rectTo.centerXOffset = this.centerXOffset;
		rectTo.centerYOffset = this.centerYOffset;
	}
}

/* Game object */
function Game(settings, draw){
	this.draw = draw;
	
	this.tanks = new Array();
	this.myTankId = -1;	//Inicialize with undefined tank ID
	
	this.createTank = createTank;
	function createTank(color, x, y, isMy){
		isMy = typeof isMy !== 'undefined' ? isMy : false;
		this.tanks.push( new Tank( this.draw, color, x, y, isMy ) );	

		if( isMy ){
			this.myTankId = this.tanks.length - 1;
			var _this = this;
			window.addEventListener('keypress', function(e){ _this.keyPressed(e) }, false);
		}
	}
	
	this.moveTank = moveTank;
	function moveTank(tankId, direction, value){
		if(tankId < 0)
			return false;
			
		this.tanks[tankId].move(direction, value);
	}
	
	this.isTankInFront = isTankInFront;
	function isTankInFront(tankId){
		var tank = this.tanks[tankId];		
		var front = tank.getFront( tankSize.headX  );
		
		for(i in this.tanks){	//Test colision with all tanks
			if( i == tankId)
				continue;
				
			var rect = this.tanks[i].rect;
			var coords = rect.getRealCoords();
			
			//WARNING: this is only for angles 0, 90, 180, 270 !!!!!!!!!!!!!!!!!!!!!!!
			var simpCoords = new Array();	
			simpCoords[0] = getMinFromArray( coords, 'x');
			simpCoords[1] = getMinFromArray( coords, 'y');
			simpCoords[2] = getMaxFromArray( coords, 'x');
			simpCoords[3] = getMaxFromArray( coords, 'y');
			
			//console.log(front);
			//console.log(simpCoords);
			
			//WARNING: this is only for angles 0, 90, 180, 270 !!!!!!!!!!!!!!!!!!!!!!!
			if( isRectangleColision(front[0], front[1], front[2], front[3], simpCoords[0], simpCoords[1], simpCoords[2], simpCoords[3]) )
				return true;
		}
		
		return false;
	}
	
	this.keyPressed = keyPressed;
	function keyPressed(e){
		var key = getKeyCode(e);
		
		var direction = -1;
		if( key == 115)	//s
			direction = 'd';
		if( key == 119)	//w
			direction = 'u';
		if( key == 100)	//d
			direction = 'r';
		if( key == 97)	//a
			direction = 'l';
			
		if( direction < 0 )
			return;
			
		/*this.tanks[this.myTankId].rect.rotation = getRotationFromDirection(direction);	//Try it, if there is a tank
		if( this.isTankInFront(this.myTankId) )
			return;
		
		this.tanks[this.myTankId].rect.rotation = getRotationFromDirection(direction, true);	//Then return it back*/
		
		this.moveTank( this.myTankId, direction, 1 );		
		
		if( this.isTankInFront(this.myTankId) )
			this.tanks[this.myTankId].moveBack();
			
		this.tanks[this.myTankId].redraw();
	}
	
}

/* Tank object */ 
function Tank(draw, color, spawnX, spawnY, isMy){
	this.draw = draw;
	
	this.isMy = isMy;
	
	this.color = color;

	this.rect = new Rectangle(spawnX, spawnY, 0, 0, 0);
	this.draw.drawTank(this.color, this.rect); //Create tank
	
	this.lastRect = new Rectangle(0,0,0,0);
	this.rect.copy(this.lastRect);

	//var points = this.rect.getRealCoords();
	//console.log(coor);
	
	//for(i in points)
		//myDebug.debugPoint(points[i]['x'], points[i]['y'], '#0000ff', 3);
	//myDebug.showRect(this.rect);
	
	this.move = move;
	function move(direction, value){
		console.log(this.isSoilInFront(5));
		if( !this.isSoilInFront( 5 ) )
			value *= 3;
		
		this.rect.copy(this.lastRect);
		
		//this.draw.eraseTank(this.rect);

		if(direction == 'd') {	//Down
			this.rect.y += value;
		}
		else if(direction == 'u') {	//Up
			this.rect.y -= value;
		}
		else if(direction == 'r') {	//Right
			this.rect.x += value;
		}
		else if(direction == 'l') {	//Left
			this.rect.x -= value;
		}
		
		this.rect.rotation = getRotationFromDirection(direction);
				
		//this.draw.drawTank( this.color, this.rect ); //Create tank
	}
	
	this.getFront = getFront;
	function getFront(distance){
		var frontPoints = new Array();
		var points = this.rect.getRealCoords();
		
		frontPoints[0] = points[2];
		frontPoints[1] = points[3];
		
		frontPoints[2] = movePointFront(points[2]['x'], points[2]['y'], this.rect.rotation, distance);
		frontPoints[3] = movePointFront(points[3]['x'], points[3]['y'], this.rect.rotation, distance);
		
		round(frontPoints);
		
		//for(var i in frontPoints)
			//myDebug.debugPoint(frontPoints[i]['x'], frontPoints[i]['y'], '#ff0000', 3);
		
		var ret = new Array();	
		ret[0] = getMinFromArray( frontPoints, 'x');
		ret[1] = getMinFromArray( frontPoints, 'y');
		ret[2] = getMaxFromArray( frontPoints, 'x');
		ret[3] = getMaxFromArray( frontPoints, 'y');
		
		return ret;
	}
	
	this.getFrontPixels = getFrontPixels;
	function getFrontPixels(distance){		
		var frontPoints = this.getFront(distance);
		
		var pixels = new Array();
		/*for(var y = yFrom; y <= yTo; y++)	
			for(var x = xFrom; x <= xTo; x++){*/
				//WARNING: this is only for angles 0, 90, 180, 270 !!!!!!!!!!!!!!!!!!!!!!!
				/*if( !isPointInRectangle( x, y, xFrom, yFrom, xTo, yTo ) )	
					continue;*/
				
				/*var pixel = this.draw.drawArea.getImageData(x, y, 1, 1);
				//console.log(x+' | '+y);
				//myDebug.debugPoint(x, y, 'yellow', 0.5, 0.5);
				pixels.push(pixel);
			}*/
			
		//WARNING: this is only for angles 0, 90, 180, 270 !!!!!!!!!!!!!!!!!!!!!!!
		pixels = this.draw.drawArea.getImageData(
			frontPoints[0], 
			frontPoints[1],
			frontPoints[2] - frontPoints[0], 
			frontPoints[3] - frontPoints[1]
		);
		return pixels;
	}
	
	this.isSoilInFront = isSoilInFront;
	function isSoilInFront(distance){
		var pixels = this.getFrontPixels(distance);
		
		if( !pixels )
			return true;
		
		var sum = 0;
		for (var i = 0; i < pixels.data.length; i += 4)	{
			var r = pixels.data[i];
			var g = pixels.data[i+1];
			var b = pixels.data[i+2];
			
			var headColor = rgbToArray( settings.tankHeadColor );
			
			if( headColor[0] == r && headColor[1] == g && headColor[2] == b )//Exclude head of tank
				continue;
			
			//console.log(r+' | '+g+' | '+b);
			
			sum += r + g + b;
			
		}
		//console.log(sum);
		if( sum <= 255 * distance )	//Black with toleration
			return false;
		else
			return true;
	}	
	
	this.moveBack = moveBack;
	function moveBack(){
		//this.draw.eraseTank(this.rect);

		this.lastRect.copy(this.rect);
				
		//this.draw.drawTank( this.color, this.rect ); //Create tank
	}
	
	this.redraw = redraw;
	function redraw(){				
		this.draw.eraseTank( this.lastRect );				
		this.draw.drawTank( this.color, this.rect ); //Create tank
	}
	
}

/* Public functions */
function changeColor(color, value){
	var rgb = rgbToArray(color);
	if( rgb === false)
		return false;
		
	var r = rgb[0] * value;
	var g = rgb[1] * value;
	var b = rgb[2] * value;
	
	if( r <= 10 && g <= 10 && b <= 10){	//If color is black
		r = 50;
		g = 50;
		b = 50;
	}
	
	return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}

function getCenterOfRectangle(x, y, width, height){
	var center = new Array();
	center['x'] = x + (0.5 * width);
	center['y'] = y + (0.5 * height);
	
	return center;
}

function isRectangleColision(x1, y1, x2, y2, r2x1, r2y1, r2x2, r2y2){	//Test colision front rectangle with regular rectangle
	if( x1 >= r2x1 && x1 <= r2x2)
		if( y1 >= r2y1 && y1 <= r2y2)
			return true;
	
	if( x2 >= r2x1 && x2 <= r2x2)
		if( y2 >= r2y1 && y2 <= r2y2)
			return true;
	
	return false;
}

function roundCoord(coord){
	return roundTo(coord, 0);
}

function rgbToArray(color){
	var arr = new Array();
	
	var rgb = color.split(',');
	arr[0] = rgb[0].split('(');
	arr[0] = round( parseInt( arr[0][1] ) );
	arr[1] = round( parseInt( rgb[1] ) );
	arr[2] = round( parseInt( rgb[2] ) );
	
	for( var i in arr )
		if( arr[i] < 0 || arr[i] > 255 || isNaN(arr[i]) )
			return false;
	
	return arr;
}


function getRotationFromDirection(direction){
	if(direction == 'd')	//Down
		return 0;
	else if(direction == 'u') 	//Up
		return 180;
	else if(direction == 'r') 	//Right
		return 270;
	else if(direction == 'l') //Left
		return 90;
}

function inverseDirection(direction){
	if(direction == 'd')	//Down
		return 'u';
	else if(direction == 'u') 	//Up
		return 'd';
	else if(direction == 'r') 	//Right
		return 'l';
	else if(direction == 'l') //Left
		return 'r';
}