//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

EMenuItemStyle =
{
	Title: "title",
	Medium : "medium",
	Small : "small",
	Tiny : "tiny",
	BlockOption: "blockOption",
	TileOption: "tileOption",
	BackgroundOption: "bgOption",
	TextOption: "TextOption",
	TextTitle: "TextTitle",
	TextSubtitle: "TextSubtitle",
	StatsBlock: "StatsBlock",
	StatsText: "StatsText",
	SmallThin: "smallThin",
	PadControls: "PadControls"
}

EMenuLayout = 
{
	Vertical : "vertical",
	Grid : "grid",
}
 
function MenuGrid(cols, rows, width, height)
{
	this.rows = rows;
	this.cols = cols;
}

function Menu(name, layout, info)
{
	this.name = name;
	this.menuItems = new Array();
	this.isRegistered = false;
	this.layout = layout;
	this.info = info;
	this.x = gDraw.canvas.width / 2;
	this.y = kTileSize * 2
	this.spacing = kTileSizeD2;
	this.selectedItem = -1;
	
	this.Resize = function()
	{
		this.x = (gDraw.canvas.width / 2);
		this.y = kTileSize * 2
		this.spacing = kTileSizeD2;
		
		var count = this.menuItems.length;
		for(var i = 0; i < count; i++)
		{
			var item = this.menuItems[i];
			this.SetMenuItemStyle(item, item.style);
		}
		
		this.UpdateLayout();
	}

	this.Registered = function()
	{
		this.isRegistered = true;
		this.UpdateLayout();
		
		if(this.selectedItem == -1)
		{
			this.SelectNextItem(1);
		}
		else
		{
			this.SelectItem(this.selectedItem);
		}
		
		if(gInputType == EInputType.Mouse)
		{
			this.InteractMove(gInteraction.mouseX, gInteraction.mouseY)
		}
	}

	this.Unregistered = function()
	{
		this.isRegistered = false;
	}

	this.UpdateLayout = function()
	{
		switch(this.layout)
		{
			case EMenuLayout.Vertical:
				this.UpdateLayoutVertical();
				break;
			case EMenuLayout.Grid:
				this.UpdateLayoutGrid();
				break;
		}
	}

	this.UpdateLayoutVertical = function()
	{
		var x = this.x;
		var y = this.y;

		var count = this.menuItems.length;
		for(var i = 0; i < count; i++)
		{
			var item = this.menuItems[i];
			item.SetPosition(x, y);
			var next = this.menuItems[i + 1];
			if(next)
			{
				y += (item.GetHeight()/2 + next.GetHeight()/2 + this.spacing);
			}

			gConsole.Log(11, "[MENU] " + item.name + " (" + item.GetX() + ", " + item.GetY() + ") - " + item.GetWidth() + ", " + item.GetHeight());
		}
	}
	
	this.UpdateLayoutGrid = function()
	{
		var rows = this.info.rows;
		var cols = this.info.cols;
		var width = gDraw.canvas.width;
		var height = gDraw.canvas.height;
		
		var xstep = width/cols;
		var ystep = height/rows;
		
		var count = this.menuItems.length;
		for(var i = 0; i < count; i++)
		{
			var item = this.menuItems[i];
			var x = (item.info.x * xstep) + (xstep * 0.5);
			var y = (item.info.y * ystep) + (ystep * 0.5);
			item.SetPosition(x, y);
			gConsole.Log(11, "[MENU] " + item.name + " (" + item.GetX() + ", " + item.GetY() + ") - " + item.GetWidth() + ", " + item.GetHeight());
		}
	}

	this.AddMenuItem = function(menuItem, style, info)
	{
		menuItem.style = style;
		menuItem.info = info;
		this.SetMenuItemStyle(menuItem, style);
		this.menuItems.push(menuItem);
	}

	this.AddMenuItemAtIndex = function(menuItem, style, index)
	{
		menuItem.style = style;
		this.SetMenuItemStyle(menuItem, style);
		this.menuItems.splice(index, 0, menuItem);
	}
	
	this.RemoveMenuItemAtIndex = function(index)
	{
		this.menuItems.splice(index, 1);
	}
	
	this.SetMenuItemStyle = function(menuItem, style)
	{
		var width = this.GetMenuItemWidth(style);
		var height = this.GetMenuItemHeight(style);
		var fontSize = this.GetMenuItemFontSize(style);
		menuItem.SetSize(width, height);
		menuItem.SetFontSize(fontSize);
	}
	
	this.GetMenuItemWidth = function(style)
	{
		switch(style)
		{
			case EMenuItemStyle.Title:
			case EMenuItemStyle.StatsBlock:
			case EMenuItemStyle.StatsText:
			{
				return kTileSize * 14;
			}
			break;
			case EMenuItemStyle.BlockOption:
			case EMenuItemStyle.TileOption:
			case EMenuItemStyle.BackgroundOption:
			case EMenuItemStyle.Medium:
			case EMenuItemStyle.TextTitle:
			case EMenuItemStyle.TextSubtitle:
			{
				return kTileSize * 5;
			}
			break;
			case EMenuItemStyle.Tiny:
			case EMenuItemStyle.Small:
			{
				return kTileSize * 5;
			}
			break;
			case EMenuItemStyle.PadControls:
			{
				return kTileSize * 14;
			}
			break;
			case EMenuItemStyle.TextOption:
			{
				return kTileSize * 10;
			}
			break;
			case EMenuItemStyle.SmallThin:
			{
				return kTileSize * 3;
			}
			break;
		}
		return kTileSize;
	}
	
	this.GetMenuItemHeight = function(style)
	{
		switch(style)
		{
			case EMenuItemStyle.StatsBlock:
			{
				return kTileSize * 3.5;
			}
			break;
			case EMenuItemStyle.Title:
			{
				return kTileSize * 3;
			}
			break;
			case EMenuItemStyle.Medium:
			{
				return kTileSize * 1.5;
			}
			break;
			case EMenuItemStyle.BackgroundOption:
			case EMenuItemStyle.Small:
			case EMenuItemStyle.SmallThin:
			case EMenuItemStyle.StatsBlock:
			{
				return kTileSize;
			}
			break;
			case EMenuItemStyle.PadControls:
			{
				return kTileSize * 7;
			}
			case EMenuItemStyle.TextOption:
			{
				return kTileSize * 0.7;
			}
			break;
			case EMenuItemStyle.TextTitle:
			case EMenuItemStyle.TextSubtitle:
			case EMenuItemStyle.Tiny:
			case EMenuItemStyle.StatsText:
			{
				return kTileSize * 0.5;
			}
			break;
			case EMenuItemStyle.BlockOption:
			{
				return kTileSize * 2;
			}
			break;
			case EMenuItemStyle.TileOption:
			{
				return kTileSize * 2.5;
			}
			break;
		}
		return kTileSize;
	}
	
	this.GetMenuItemFontSize = function(style)
	{
		switch(style)
		{
			case EMenuItemStyle.Title:
			{
				return GetFontScale(102);
			}
			break;
			case EMenuItemStyle.Medium:
			case EMenuItemStyle.TextTitle:
			{
				return GetFontScale(36);
			}
			break;
			case EMenuItemStyle.BlockOption:
			case EMenuItemStyle.TileOption:
			case EMenuItemStyle.BackgroundOption:
			case EMenuItemStyle.Small:
			case EMenuItemStyle.SmallThin:
			case EMenuItemStyle.TextOption:
			case EMenuItemStyle.PadControls:
			case EMenuItemStyle.TextSubtitle:
			case EMenuItemStyle.StatsBlock:
			case EMenuItemStyle.StatsText:
			{
				return GetFontScale(24);
			}
			break;
			case EMenuItemStyle.Tiny:
			{
				return GetFontScale(16);
			}
			break;
		}
		
		return GetFontScale(10);
	}
	
	this.RemoveMenuItem = function(name)
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			if(this.menuItems[i].name == name)
			{
				this.menuItems.splice(i, 1);
				return;
			}
		}
	}
	
	this.KeyDown = function(key)
	{
		if(key == EKeyCode.closemenu)
		{
			for(var i = 0; i < this.menuItems.length; i++)
			{
				var menuItem = this.menuItems[i];
				if(menuItem.name == "Back" || menuItem.name == "Continue")
				{
					menuItem.Interact(true);
					return true;
				}
			}
		}

		switch(this.layout)
		{
			case EMenuLayout.Vertical:
				return this.KeyDownLayoutVertical(key);
			case EMenuLayout.Grid:
				return this.KeyDownLayoutGrid(key);
		}
		return false;
	}
	
	this.KeyDownLayoutVertical = function(key)
	{
		switch(key)
		{
			case EKeyCode.left:
			case EKeyCode.a:
				var item = this.menuItems[this.selectedItem];
				if(item && item.SelectLeft)
				{
					item.SelectLeft();
				}
				return true;
			case EKeyCode.right:
			case EKeyCode.d:
				var item = this.menuItems[this.selectedItem];
				if(item && item.SelectRight)
				{
					item.SelectRight();
				}
				return true;
			case EKeyCode.up:
			case EKeyCode.w:
				this.SelectNextItem(-1);
				return true;
			case EKeyCode.down:
			case EKeyCode.s:
				this.SelectNextItem(1);
				return true;
		}

		return false;
	}
	
	this.KeyDownLayoutGrid = function(key)
	{
		switch(key)
		{
			case EKeyCode.left:
			case EKeyCode.a:
				this.SelectButton(this.ScoreGridLeft);
				return true;
			case EKeyCode.right:
			case EKeyCode.d:
				this.SelectButton(this.ScoreGridRight);
				return true;
			case EKeyCode.up:
			case EKeyCode.w:
				this.SelectButton(this.ScoreGridUp);
				return true;
			case EKeyCode.down:
			case EKeyCode.s:
				this.SelectButton(this.ScoreGridDown);
				return true;
		}

		return false;
	}
		
	this.SelectButton = function(scoreItemFunc)
	{
		var selectedItem = this.menuItems[this.selectedItem];
		if(selectedItem)
		{
			var nextItemIndex = undefined;
			var nextItemScore = Number.MAX_VALUE;
			for(var i = 0; i < this.menuItems.length; i++)
			{
				if(i != this.selectedItem)
				{
					var item = this.menuItems[i];
					var score = scoreItemFunc(selectedItem, item);
					if(score < nextItemScore)
					{
						nextItemIndex = i;
						nextItemScore = score;
					}
				}
			}
			
			if(nextItemIndex != undefined)
			{
				this.SelectItem(nextItemIndex);
			}
		}
	}
	
	this.ScoreGridRight = function(selected, item)
	{
		if(selected.info.x < item.info.x)
		{
			if(selected.info.y == item.info.y)
			{
				return item.info.x - selected.info.x;
			}
			else
			{
				return (item.info.x - selected.info.x) + (Math.abs(selected.info.y - item.info.y) * 10);
			}
		}
		
		return Number.MAX_VALUE;
	}

	this.ScoreGridLeft = function(selected, item)
	{
		if(selected.info.x > item.info.x)
		{
			if(selected.info.y == item.info.y)
			{
				return selected.info.x - item.info.x;
			}
			else
			{
				return (selected.info.x - item.info.x) + (Math.abs(selected.info.y - item.info.y) * 10);
			}
		}
		
		return Number.MAX_VALUE;
	}
	
	this.ScoreGridDown = function(selected, item)
	{
		if(selected.info.y < item.info.y)
		{
			if(selected.info.x == item.info.x)
			{
				return item.info.y - selected.info.y;
			}
			else
			{
				return (item.info.y - selected.info.y) + (Math.abs(selected.info.x - item.info.x) * 10);
			}
		}
		
		return Number.MAX_VALUE;
	}
	
	this.ScoreGridUp = function(selected, item)
	{
		if(selected.info.y > item.info.y)
		{
			if(selected.info.x == item.info.x)
			{
				return selected.info.y - item.info.y;
			}
			else
			{
				return (selected.info.y - item.info.y) + (Math.abs(selected.info.x - item.info.x) * 10);
			}
		}
		
		return Number.MAX_VALUE;
	}
	
	
	this.KeyUp = function(key)
	{
		switch(key)
		{
			case EKeyCode.space:
			case EKeyCode.return:
				var item = this.menuItems[this.selectedItem];
				if(item && item.Interact)
				{
					item.Interact();
				}
				return true;
		}
		return false;
	}
	
	this.SelectNextItem = function(direction)
	{
		var targetItem = this.selectedItem + direction;
		for(var i = 0; i < this.menuItems.length; i++)
		{
			if(targetItem < 0)
			{
				targetItem = this.menuItems.length - 1;
			}
			else if(targetItem > this.menuItems.length - 1)
			{
				targetItem = 0;
			}
			
			if(this.SelectItem(targetItem))
			{
				return;
			}
			
			targetItem += direction;
		}
	}
	
	this.SelectItem = function(index)
	{
		if(this.CanSelectItem(index))
		{
			var item = this.menuItems[index];
			if(item.SelectedItem)
			{
				item.SelectedItem();
			}
			this.SetSelectedItem(index);
			return true;
		}
		
		return false;
	}
	
	this.CanSelectItem = function(index)
	{
		var item = this.menuItems[index];
		return item && item.CanSelect();
	}
	
	this.SetSelectedItem = function(index)
	{
		if(this.selectedItem != index)
		{
			gConsole.Log(11, "[MENU] SetSelectedItem " + index);
	
			var item = this.menuItems[index];
			if(item)
			{
				item.PlayHighlightSound();
			}
	
			this.selectedItem = index;
		}
	}
	
	this.InteractMove = function(x, y)
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			var item = this.menuItems[i];
			if(item.IsVisible() && item.CanInteract && item.CanInteract(x, y))
			{
				if(item.InteractMove)
				{
					item.InteractMove(x, y);
				}
				this.SetSelectedItem(i);
				return true;
			}
		}
		
		return false;
	}
	
	this.InteractRelease = function(x, y)
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			var item = this.menuItems[i];
			if(item.IsVisible() && item.InteractRelease && item.InteractRelease(x, y))
			{
				return true;
			}
		}
		
		return false;
	}

	this.Redraw = function()
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			if(this.menuItems[i].Redraw)
			{
				this.menuItems[i].Redraw();
			}
		}
	}

	this.DrawClear = function()
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			this.menuItems[i].DrawClear();
		}
	}
	
	this.Draw = function()
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			var item = this.menuItems[i];
			if(item.IsVisible())
			{
				item.Draw(i == this.selectedItem);
			}
		}
	}
	
	this.Update = function()
	{
		for(var i = 0; i < this.menuItems.length; i++)
		{
			this.menuItems[i].Update(i == this.selectedItem);
		}
	}
}
