//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 gStyles = new Styles();

function LightSource(x, y, range, strength)
{
	this.x = x;
	this.y = y;
	this.range = range;
	this.strength = strength;
	
	this.GetBrightness = function(x, y)
	{
		if(this.range > 0)
		{
			var dist = distance(this.x, this.y, x, y);
			var inverseDist = Math.clamp(this.range - dist, 0, this.range)/this.range;
			return Math.round(inverseDist * this.strength);
		}
		else
		{
			return 0;
		}
	}
	
	this.IsValid = function()
	{
		return this.range > 0 && this.strength > 0;
	}
	
	this.GetPixelX = function()
	{
		return (this.x * kTileSize) + kTileSizeD2;
	}
	
	this.GetPixelY = function()
	{
		return (this.y * kTileSize) + kTileSizeD2;
	}
	
	this.GetPixelRadius = function()
	{
		return this.range * kTileSize;
	}
	
	this.Debug = function()
	{
		var px = this.GetPixelX();
		var py = this.GetPixelY();
		var range = this.GetPixelRadius();
		gDraw.debug.beginPath();
		gDraw.debug.arc(px, py, range, Math.PI * 2, false);
		gDraw.debug.closePath();
		gDraw.debug.fillStyle = "rgba(255, 255, 255, 0.05)";
		gDraw.debug.fill();
		gDraw.debug.strokeStyle = "rgba(255, 255, 255, 0.2)";
		gDraw.debug.stroke();
		
		for(var x = 0; x < gTileWidth; x++)
		{
			for(var y = 0; y < gTileHeight; y++)
			{
				var brightness = this.GetBrightness(x, y);
				if(brightness > 0)
				{
					var px = (x * kTileSize) + kTileSizeD2;
					var py = (y * kTileSize) + kTileSizeD2;
					gDraw.WatchAt(px, py, brightness);
				}
			}
		}
	}
}

function Styles()
{
	this.lightSources = new Array();
	
	this.Init = function()
	{
		this.Resize();
	}
	
	this.Resize = function()
	{
		this.blockRounding = new Array();
		this.blockRounding[EBlockType.Static] = 0;
		this.blockRounding[EBlockType.Normal] = kTileSize * 0.18;
		this.blockRounding[EBlockType.Sliding] = kTileSize * 0.42;
	}
	
	this.SetNormalizedColor = function(r, g, b)
	{
		this.SetColor(Math.round(r * 255), Math.round(g * 255), Math.round(b * 255));
		gBlockSystem.Redraw();
	}
	
	this.SetColor = function(r, g, b)
	{
		gConsole.Log(3, "[STYLE] Setting color " + r + ", " + g + ", " + b);
		this.baseColor = new RGB(r, g, b);
		this.baseColorHSV = this.baseColor.GetHSV();
		var newPlayerFill = this.baseColor.GetInverted();
		this.prevPlayerFill = this.playerFill ? this.playerFill : newPlayerFill;
		this.playerFill = newPlayerFill;
		this.playerFillA32 = newPlayerFill.GetAdjusted(32);
		this.playerFillM32 = newPlayerFill.GetAdjusted(-32);
		this.targetPlayerFill = newPlayerFill;

		var newTileFill = this.baseColorHSV.GetAdjustedVariance(-50).GetRGB();
		this.prevTileFill = this.tileFill ? this.tileFill : newTileFill;
		this.tileFill = newTileFill;
		this.targetTileFill = newTileFill;

		var newBackgroundFill = this.tileFill.GetAdjusted(-42);
		this.prevBackgroundFill = this.backgroundFill ? this.backgroundFill : newBackgroundFill;
		this.backgroundFill = newBackgroundFill;
		this.targetBackgroundFill = newBackgroundFill;
		gBackground.Redraw();
		gTileSystem.redraw = true;

		this.SetBlockColor();
		
		if(gEditor)
		{
			var el = document.getElementById("Color");
			if(el && el.color)
			{
				el.color.fromRGB(r/255, g/255, b/255);
			}
		}
	}
	
	this.SetBlockColor = function()
	{
		this.blockStyles = new Array();
		for(var i = 1; i < 10; i++)
		{
			this.blockStyles[i] = this.baseColorHSV.GetAdjustedHue((5 - i) * 12).GetRGB();
		}
		this.blockDeletingStyles = new Array();
		for(var i = 1; i < 10; i++)
		{
			this.blockDeletingStyles[i] = this.blockStyles[i].GetScaled(0.5);
		}
	}
	
	this.Clear = function()
	{
		this.lightSources = new Array();
	}
	
	this.AddLightSource = function(x, y, range, strength)
	{
		this.lightSources.push(new LightSource(x, y, range, strength));
	}

	this.InitLights = function()
	{
		this.AllocLights();

		for(var l = 0; l < this.lightSources.length; l++)
		{
			var light = this.lightSources[l];
			for(var x = 0; x < gTileWidth; x++)
			{
				for(var y = 0; y < gTileHeight; y++)
				{
					this.light[x][y] += light.GetBrightness(x, y);
				}
			}
		}
		gTileSystem.redraw = true;

		if(gEditor)
		{
			EditorLightSet();
		}
	}
	
	this.AllocLights = function()
	{
		this.light = new Array();
		for(var x = 0; x < gTileWidth; x++)
		{
			this.light[x] = new Array();
			for(var y = 0; y < gTileHeight; y++)
			{
				this.light[x][y] = 0;
			}
		}	
	}
	
	this.Debug = function()
	{
		var urlVars = getUrlVars();
		if(urlVars["color"])
		{
			this.DebugColor();
		}
		if(urlVars["lights"])
		{
			this.DebugLights();
		}
		if(urlVars["light"])
		{
			this.DebugLight();
		}
	}
	
	this.DebugColor = function()
	{
		gDraw.Watch("Style  " + this.baseColor.GetColor());
	}
	
	this.DebugLights = function()
	{
		for(var l = 0; l < this.lightSources.length; l++)
		{
			this.lightSources[l].Debug();
		}
	}

	this.DebugLight = function()
	{
		for(var x = 0; x < gTileWidth; x++)
		{
			for(var y = 0; y < gTileHeight; y++)
			{
				var px = (x * kTileSize) + kTileSizeD2;
				var py = (y * kTileSize) + kTileSizeD2;
				gDraw.WatchAt(px, py, this.light[x][y]);
			}
		}
	}

	this.GetBlockFillStyle = function(block)
	{
		//linear gradient render
		var rgb = this.GetBlockRGB(block.type, block.value, block.IsDeleting() && block.fading);
		
		var fraction = block.GetAlphaFraction();
		var a = 1 - fraction;
		
		var x = (block.x * kTileSize);
		var y = (block.y * kTileSize);

		var widthD2 = block.GetBlockWidth() * 0.5;
		var height = block.GetBlockHeight() * 0.5;
		var gradient  = gDraw.context.createLinearGradient(x + widthD2, y, x + widthD2, y + height);
		
		gradient.addColorStop(0.0, this.GetColorAlpha(rgb.GetAdjusted(24), a));
		gradient.addColorStop(1.0, this.GetColorAlpha(rgb.GetAdjusted(-24), a));

		return gradient;
	}
	
	this.GetBlockOutlineStrokeStyle = function(block)
	{
		var rgb = this.GetBlockRGB(block.type, block.value, false);
		return this.GetColor(rgb);
	}
	
	this.GetBlockStrokeStyle = function(block)
	{
		return "rgba(255, 255, 255, 0.5)";
		/*
		var rgb = this.GetBlockRGB(block.type, block.value, block.IsDeleting());
		
		var fraction = block.GetAlphaFraction();
		var a = 1 - fraction;
		
		return this.GetColorAlpha(rgb.GetHSV().GetAdjustedHue(7).GetRGB().GetAdjusted(64), a);
		*/
	}
	
	this.returnTileFill = new RGB(0, 0, 0);
	this.GetTileFillStyle = function(tile)
	{
		this.returnTileFill.Copy(this.tileFill);
		var extraLight = 0;
		var firstPlayer = gPlayerSystem.players[0]
		if(firstPlayer)
		{
			var dist = Math.abs(tile.x - firstPlayer.x) + Math.abs(tile.y - firstPlayer.y);
			if(dist <= 2.5)
			{
				extraLight = Math.round((2.5 - dist) * 10);
			}
		}
		var x = (tile.x * kTileSize);
		var y = (tile.y * kTileSize);
		var light = this.light[tile.x][tile.y] + extraLight;
		if(light)
		{
			this.returnTileFill.Adjust(light);
		}
		
		return this.returnTileFill.GetColor();
	}

	this.GetColor = function(rgb)
	{
		return "rgb(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ")";
	}
	
	this.GetColorAlpha = function(rgb, a)
	{
		return "rgba(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ", " + a + ")";
	}

	this.GetMaximalColor = function(rgb, rgb1, a)
	{
		var r = Math.min(rgb.r + rgb1.r, 255);
		var g = Math.min(rgb.g + rgb1.g, 255);
		var b = Math.min(rgb.b + rgb1.b, 255);
		
		return "rgba(" + r + ", " + g + ", " + b + ", " + a + ")";
	}
	
	this.GetBlockRGB = function(type, value, deleting)
	{
		var rgb = this.blockStyles[value];
		if(deleting)
		{
			return this.blockDeletingStyles[value];
		}
		return rgb;
	}
	
	this.GetBlockRounding = function(block)
	{
		var size = this.blockRounding[block.type];
		gConsole.Assert(size != undefined);
		return size;
	}
	
	this.GetBackgroundFill = function()
	{
		return this.backgroundFill.GetColor();
	}
	
	this.GetTileFill = function()
	{
		return this.tileFill.GetColor();
	}
	
	this.GetPlayerFill = function(player)
	{
		var x = (player.x * kTileSize);
		var y = (player.y * kTileSize);
		
		var light = this.light[player.GetX()][player.GetY()];
	
		var gradient  = gDraw.context.createLinearGradient(x, y, x, y + kTileSize);
		
		gradient.addColorStop(0.0, this.playerFillA32.GetAdjusted(light).GetColor());
		gradient.addColorStop(1.0, this.playerFillM32.GetAdjusted(light).GetColor());
		
		return gradient;
	}
	
	this.StartTransition = function()
	{
		this.backgroundFill = this.prevBackgroundFill;
		this.tileFill = this.prevTileFill;
		this.playerFill = this.prevPlayerFill;
		this.playerFillA32 = this.prevPlayerFill.GetAdjusted(32);
		this.playerFillM32 = this.prevPlayerFill.GetAdjusted(-32);

	}
	
	this.DrawTransition = function(fraction)
	{
		if(fraction >= 1)
		{
			this.backgroundFill = this.targetBackgroundFill;
			this.tileFill = this.targetTileFill;
			this.playerFill = this.targetPlayerFill;
			this.playerFillA32 = this.targetPlayerFill.GetAdjusted(32);
			this.playerFillM32 = this.targetPlayerFill.GetAdjusted(-32);
		}
		else
		{
			fraction = Math.pow(fraction, 2);
			this.backgroundFill = this.prevBackgroundFill.GetBlend(this.targetBackgroundFill, fraction);
			this.tileFill = this.prevTileFill.GetBlend(this.targetTileFill, fraction);
			this.playerFill = this.prevPlayerFill.GetBlend(this.targetPlayerFill, fraction);
			this.playerFillA32 = this.playerFill.GetAdjusted(32);
			this.playerFillM32 = this.playerFill.GetAdjusted(-32);
		}
	}
	
	this.Init();
}
