//Copyright (C) Ben Parbury - All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited. Written by Ben Parbury <ben@gridlockinteractive.com> 2014

var kTileSize = 50;
var kTileSizeD2 = kTileSize/2;

ETileType =
{
	Normal : "normal",
	Conveyor : "conveyor",
	Slider : "slider",
	Hint : "hint"
}

EConveyorSubType =
{
	Up : "up",
	Down : "down",
	Left : "left",
	Right : "right"
}

var gTileStyle = 0;
var gTileBGStyle = 0;

/*var prevStyle = gStorage.getItem("options", "tiles", "style");
if(prevStyle)
{
	gTileStyle = parseInt(prevStyle);
}*/
var gTileBGContext = gDraw.tilebg;
var gTileContext = gDraw.tiles;

function PrevTileStyle()
{
	gTileStyle--;
	if (gTileStyle < 0)
	{
		gTileStyle = 3;
	}
	gStorage.setItem("options", "tiles", "style", gTileStyle);
	gTileSystem.redraw = true;
	gTileSystem.Draw();
}

function NextTileStyle()
{
	gTileStyle++;
	if (gTileStyle > 3)
	{
		gTileStyle = 0;
	}
	gStorage.setItem("options", "tiles", "style", gTileStyle);
	gTileSystem.redraw = true;
	gTileSystem.Draw();
}

function ValidTileType(typeCheck)
{
	for(var type in ETileType)
	{
		if(ETileType[type] == typeCheck)
		{
			return true;
		}
	}
	return false;
}

function Tile()
{
	this.type = 0;
	this.x = 0;
	this.y = 0;

	this.blockMove = true;
	this.playerMove = true;

	this.Init = function(type, x, y, blockMove, playerMove)
	{
		gConsole.Assert(ValidTileType(type));
		this.type = type;
		this.x = x;
		this.y = y;
		this.blockMove = blockMove;
		this.playerMove = playerMove;
	}
	
	this.DrawBackground = function()
	{
		this.BGstyles[gTileBGStyle].call(this);
	}
	
	this.DrawBackgroundPlain = function()
	{
		gTileBGContext.fillStyle = gStyles.tileFill.GetAdjusted(-16).GetColor();
		gTileBGContext.beginPath();
		var x = (this.x * kTileSize);
		var y = (this.y * kTileSize);
		var edgeSize = kTileSize * 0.25;
		var sizeChange = (edgeSize * 2) + 1
		gTileBGContext.rect(x - edgeSize, y - edgeSize, kTileSize + sizeChange, kTileSize + sizeChange);
		gTileBGContext.fill();
	}

	this.DrawBackgroundRound = function()
	{
		gTileBGContext.fillStyle = gStyles.tileFill.GetAdjusted(-16).GetColor();
		gTileBGContext.beginPath();
		var x = (this.x * kTileSize) + kTileSizeD2;
		var y = (this.y * kTileSize) + kTileSizeD2;
		gTileBGContext.arc(x, y, kTileSizeD2 * 1.618, 0, Math.PI * 2);
		gTileBGContext.fill();
	}
	
	/*this.aztecPositions = new Array(
			new Vec2(2, 0), new Vec2(3, 1), new Vec2(4, 0), new Vec2(5, 1), new Vec2(6, 0),
			new Vec2(8, 2), new Vec2(7, 3), new Vec2(8, 4), new Vec2(7, 5), new Vec2(8, 6),
			new Vec2(6, 8), new Vec2(5, 7), new Vec2(4, 8), new Vec2(3, 7),new Vec2(2, 8),
			new Vec2(0, 6), new Vec2(1, 5), new Vec2(0, 4), new Vec2(1, 3), new Vec2(0, 2));*/
	this.aztecPositions = new Array(
			new Vec2(4, -2.1), new Vec2(10.1, 4), new Vec2(4, 10.1), new Vec2(-2.1, 4));
	this.DrawBackgroundAztec = function()
	{
		gTileBGContext.fillStyle = gStyles.tileFill.GetAdjusted(-16).GetColor();
		
		gTileBGContext.beginPath();
		var size = kTileSize * 1.333;
		var step = size/8;
		var xstart = (this.x * kTileSize) - step;
		var ystart = (this.y * kTileSize) - step;
		
		var length = this.aztecPositions.length;
		for(var i = 0; i < length; i++)
		{
			var xpos = xstart + (this.aztecPositions[i].x * step)
			var ypos = ystart + (this.aztecPositions[i].y * step)
			if(i == 0)
			{
				gTileBGContext.moveTo(xpos, ypos);
			}
			else
			{
				gTileBGContext.lineTo(xpos, ypos);
			}
		}
		
		gTileBGContext.closePath();
		gTileBGContext.fill();
	}
	
	this.DrawPlain = function(x, y)
	{
		gTileContext.beginPath();
		var edge = kTileSize * 0.01;
		gTileContext.rect(x + edge, y + edge, kTileSize - (2 * edge), kTileSize - (2 * edge));
		
		gTileContext.fillStyle = gStyles.GetTileFillStyle(this);
		gTileContext.fill();
	}
	
	this.DrawRounded = function(x, y)
	{
		gTileContext.beginPath();
		var edge = kTileSize * 0.02;
		gTileContext.fillStyle = gStyles.GetTileFillStyle(this);
		gTileContext.fillRoundedRect(x + edge, y + edge, kTileSize - (2 * edge), kTileSize - (2 * edge), kTileSize * 0.1);
	}
	
	this.DrawOct = function(x, y)
	{
		gTileContext.beginPath();
		var edge = kTileSize * 0.02;
		var corner = kTileSize * 0.16;
		gTileContext.moveTo(x + corner, y + edge);
		gTileContext.lineTo(x + kTileSize - corner, y + edge);
		
		gTileContext.lineTo(x + kTileSize - edge, y + corner);
		gTileContext.lineTo(x + kTileSize - edge, y + kTileSize - corner);
		
		gTileContext.lineTo(x + kTileSize - corner, y + kTileSize - edge);
		gTileContext.lineTo(x + corner, y + kTileSize - edge);
		
		gTileContext.lineTo(x + edge, y + kTileSize - corner);
		gTileContext.lineTo(x + edge, y + corner);
		
		gTileContext.fillStyle = gStyles.GetTileFillStyle(this);
		gTileContext.fill();
	}
	
	this.DrawSquares = function(x, y)
	{
		gTileContext.beginPath();
		gTileContext.lineWidth = kTileSize * 0.02;
		var edge = kTileSize * 0.01;
		gTileContext.rect(x + edge, y + edge, kTileSize - (2 * edge), kTileSize - (2 * edge));
		
		gTileContext.fillStyle = gStyles.GetTileFillStyle(this);
		gTileContext.fill();
		
		gTileContext.strokeStyle = gStyles.tileFill.GetAdjusted(-16).GetColor();
		for(; edge < kTileSize/2; edge += kTileSize * 0.1)
		{
			gTileContext.rect(x + edge, y + edge, kTileSize - (2 * edge), kTileSize - (2 * edge));
		}
		gTileContext.stroke();
	}
	
	this.DrawGrid = function(x, y)
	{
		gTileContext.beginPath();
		gTileContext.lineWidth = 1;
		var stepSize = kTileSize/5;
		for (var i = stepSize; i < kTileSize; i+= stepSize)
		{
			gTileContext.moveTo(x + i, y);
			gTileContext.lineTo(x + i, y + kTileSize);
		}

		for (var i = stepSize; i < kTileSize; i+= stepSize)
		{
			gTileContext.moveTo(x, y + i);
			gTileContext.lineTo(x + kTileSize, y + i);
		}
		
		gTileContext.strokeStyle = gStyles.GetTileFillStyle(this);
		gTileContext.stroke();
		
		gTileContext.beginPath();
		gTileContext.lineWidth = 2;
		gTileContext.rect(x, y, kTileSize, kTileSize);
		gTileContext.stroke();

	}

	this.Draw = function()
	{
		var x = (this.x * kTileSize);
		var y = (this.y * kTileSize);
		
		this.styles[gTileStyle].call(this, x, y);
		
		var canMoveBlockTo = this.CanMoveBlockTo();
		var canMovePlayerTo = this.CanMovePlayerTo();
		
		if(!canMoveBlockTo && !canMovePlayerTo)
		{
			var padding = kTileSize * 0.1;
			gTileContext.strokeStyle = "rgba(255, 255, 255, 0.3)";
			gTileContext.lineWidth = kTileSize * 0.1;
			gTileContext.lineJoin = "round";
			gTileContext.lineCap = "round";
			
			gTileContext.beginPath();
			gTileContext.moveTo(x + padding, y + padding);
			gTileContext.lineTo(x + kTileSize - padding, y + kTileSize - padding);

			gTileContext.moveTo(x + kTileSize - padding, y + padding);
			gTileContext.lineTo(x + padding, y + kTileSize - padding);
			gTileContext.closePath();
			
		    gTileContext.stroke();
		}
		else if(!canMoveBlockTo)
		{
			var padding = kTileSize * 0.1;
			gTileContext.strokeStyle = "rgba(255, 255, 255, 0.3)";
			gTileContext.lineWidth = kTileSize * 0.1;
			gTileContext.lineJoin = "round";
			gTileContext.lineCap = "round";
			
			gTileContext.beginPath();
			gTileContext.moveTo(x + kTileSize - padding, y + padding);
			gTileContext.lineTo(x + padding, y + kTileSize - padding);
			gTileContext.rect(x + padding, y + padding, kTileSize - (padding * 2), kTileSize - (padding * 2));
			gTileContext.closePath();
			
		    gTileContext.stroke();
		}
		else if(!canMovePlayerTo)
		{
			var padding = kTileSize * 0.1;
			gTileContext.beginPath();
			
			gTileContext.strokeStyle = "rgba(255, 255, 255, 0.3)";
			gTileContext.lineWidth = kTileSize * 0.1;
			gTileContext.lineJoin = "round";
			gTileContext.lineCap = "butt";

			gTileContext.beginPath();
			var radius = (kTileSize - (padding * 2))/2;
			gTileContext.arc(x + (kTileSizeD2), y + (kTileSizeD2), radius, Math.PI * 2, 0);
			
			var diagonalDist = radius * Math.sin(Math.PI * 0.25);
			gTileContext.moveTo(x + (kTileSizeD2) - diagonalDist, y + (kTileSizeD2) + diagonalDist);
			gTileContext.lineTo(x + (kTileSizeD2) + diagonalDist, y + (kTileSizeD2) - diagonalDist);


		    gTileContext.stroke();
		}
	}
	
	this.DrawClear = function()
	{
		var x = (this.x * kTileSize);
		var y = (this.y * kTileSize);

		gTileContext.clearRect(x, y, kTileSize, kTileSize);
	}

	this.CanMoveBlockTo = function()
	{
		return this.blockMove;
	}

	this.CanMovePlayerTo = function()
	{
		return this.playerMove;
	}
	
	this.BGstyles = new Array(
		this.DrawBackgroundPlain,
		this.DrawBackgroundRound,
		this.DrawBackgroundAztec
	)

	this.styles = new Array(
		this.DrawPlain,
		this.DrawRounded,
		this.DrawOct,
		this.DrawSquares,
		this.DrawGrid)
}

function ConveyorTile()
{
	this.__proto__ = new Tile;

	this.subType = null;

	this.dx = 0;
	this.dy = 0;

	
	this.SetSubType = function(subtype)
	{
		switch(subtype)
		{
			case EConveyorSubType.Down:
			{
				this.dx = 0;
				this.dy = 1;
				break;
			}
			case EConveyorSubType.Up:
			{
				this.dx = 0;
				this.dy = -1;
				break;
			}
			case EConveyorSubType.Left:
			{
				this.dx = -1;
				this.dy = 0;
				break;
			}
			case EConveyorSubType.Right:
			{
				this.dx = 1;
				this.dy = 0;
				break;
			}
			default:
				gConsole.AssertNow("Unknown subtype");
				break;
		}
		
		this.subType = subtype;
	}
	
	this.DrawOverlay = function()
	{
		var x = (this.x * kTileSize);
		var y = (this.y * kTileSize);

		var padding = 10;
		
		switch(this.subType)
		{
			case EConveyorSubType.Down:
			{
				startX = x + (kTileSizeD2);
				startY = y + padding;
	
				endX = x + (kTileSizeD2);
				endY = y + kTileSize - padding;
				break;
			}
			case EConveyorSubType.Up:
			{
				startX = x + (kTileSizeD2);
				startY = y + kTileSize - padding;
	
				endX = x + (kTileSizeD2);
				endY = y + padding;
				break;
			}
			case EConveyorSubType.Left:
			{
				startX = x + kTileSize - padding;
				startY = y + (kTileSizeD2);
	
				endX = x + padding;
				endY = y + (kTileSizeD2);
				break;
			}
			case EConveyorSubType.Right:
			{
				startX = x + padding;
				startY = y + (kTileSizeD2);
	
				endX = x + kTileSize - padding;
				endY = y + (kTileSizeD2);
				break;
			}
			default:
				gConsole.AssertNow("Unknown subtype");
				break;
		}
			
		gTileContext.beginPath();
		
		gTileContext.Arrow(startX, startY, endX, endY, kTileSize/3, Math.PI/4);
		
		gTileContext.strokeStyle = "rgba(255, 255, 255, 0.5)";
		gTileContext.lineWidth = 5;
		gTileContext.lineJoin = "round";
		gTileContext.lineCap = "round";
	    gTileContext.stroke();
	}

	this.Activate = function(block)
	{
		if(block.CanMove(this, this.dx, this.dy))
		{
			block.Move(this, this.dx, this.dy);
		}
	}
}

function SliderTile()
{
	this.__proto__ = new Tile;
	
	this.pDBlock = null;

	this.pDx = 0;
	this.pDy = 0;
	
	this.DrawOverlay = function()
	{
		var x = (this.x * kTileSize);
		var y = (this.y * kTileSize);
		
		gTileContext.strokeStyle = "rgba(255, 255, 255, 0.5)";
		gTileContext.lineWidth = 3;
		gTileContext.lineJoin = "round";
		gTileContext.lineCap = "round";
		
		var centerX = x + (kTileSizeD2);
		var centerY = y + (kTileSizeD2);
		var radius = (kTileSizeD2) - 10;
		var pronglength = 7;
		var prongAngle = Math.PI * 0.25;

		gTileContext.beginPath();
		for(var angle = 0; angle < Math.PI * 2; angle += Math.PI * 0.333)
		{
			this.DrawProng(centerX, centerY, radius, angle, pronglength, prongAngle);
		}
		
		gTileContext.stroke();
		
	    
	}
	
	this.DrawProng = function(x, y, radius, angle, prongLength, prongAngle)
	{
		gTileContext.moveTo(x, y);
		gTileContext.lineTo(x + (Math.cos(angle) * radius), y + (Math.sin(angle) * radius));
		
		var prongStartLength = radius - prongLength;
		var prongX = x + (Math.cos(angle) * prongStartLength);
		var prongY = y + (Math.sin(angle) * prongStartLength);
		
		gTileContext.moveTo(prongX, prongY);
		gTileContext.lineTo(prongX + (Math.cos(angle + prongAngle) * prongLength), prongY + (Math.sin(angle + prongAngle) * prongLength));
		gTileContext.moveTo(prongX, prongY);
		gTileContext.lineTo(prongX + (Math.cos(angle - prongAngle) * prongLength), prongY + (Math.sin(angle - prongAngle) * prongLength));
	}
	
	this.Activate = function(block)
	{
		if(block.tween)
		{
			this.pDBlock = block;
			this.pDx = block.dx;
			this.pDy = block.dy;
		}
		else
		{
			if((this.pDx != 0 || this.pDy != 0) && this.pDBlock == block)
			{
				//move blocks off in the direction they came on
				if(block.CanMove(this, this.pDx, this.pDy))
				{
					block.Move(this, this.pDx, this.pDy);
				}
				//then clear movement
				this.pDx = 0;
				this.pDy = 0;
			}
		}
	}
}

function HintTile()
{
	this.__proto__ = new Tile;

	this.hintText = null;
	this.hintSound = gSounds.Get("hint");

	this.SetHintText = function(hintText)
	{
		this.hintText = hintText;
	}
	
	this.DrawOverlay = function()
	{
		var x = (this.x * kTileSize) + kTileSizeD2;
		var y = (this.y * kTileSize) + kTileSizeD2;
		DrawHintIcon(x, y, gTileContext, this.IsActive());
	}

	this.PlayerActivate = function(player)
	{
		if(!this.IsActive() && !gUndoSystem.IsUndoing())
		{
			this.ShowHint();
		}
	}
	
	this.IsActive = function()
	{
		return gTileSystem.activeHintTilePos.x == this.x && gTileSystem.activeHintTilePos.y == this.y;
	}
	
	this.SetActive = function()
	{
		var prevTile = gTileSystem.GetTileAt(gTileSystem.activeHintTilePos.x, gTileSystem.activeHintTilePos.y);
		if(!gUndoSystem.IsUndoing())
		{
			gUndoSystem.AddRecord(new UndoHintTile(prevTile, this));
			this.hintSound.Play();
		}
		gTileSystem.activeHintTilePos.x = this.x;
		gTileSystem.activeHintTilePos.y = this.y;
		if(prevTile)
		{
			prevTile.DrawClear();
			prevTile.Draw();
			prevTile.DrawOverlay();
		}
	}
	
	this.ShowHint = function()
	{
		this.SetActive();
		this.DrawClear();
		this.Draw();
		this.DrawOverlay();
		gHintsOverlay.Set(this.hintText);
	}
	
	this.HideHint = function()
	{
		gTileSystem.activeHintTilePos.x = -1;
		gTileSystem.activeHintTilePos.y = -1;
		this.DrawClear();
		this.Draw();
		this.DrawOverlay();
		gHintsOverlay.Set("");
	}
}


function DrawHintIcon(x, y, context, active, scale)
{
	if(!scale)
	{
		scale = 1;
	}
	
	context.save();
	
	context.fillStyle = "rgba(255, 255, 255, 0.3)";
	context.shadowOffsetX = 0;
	context.shadowOffsetY = 0;
	context.shadowBlur = 0;


	if(active)
	{
		var radius = (kTileSizeD2 - 5) * scale;
		context.beginPath();
		context.arc(x, y, radius, 0, Math.PI * 2, true);
		context.fill();

		context.globalCompositeOperation = 'destination-out';
	}

	context.font = GetFont(GetFontScale(42) * scale);
	context.textAlign	 = 'center';
	context.textBaseline	 = 'middle';
	
	context.fillText("i", x + 0.5, y);
	
	context.restore();
}
