using UnityEngine;
using System.Collections;

public class Inventory : MonoBehaviour {
	
	public static Inventory instance;
	
	const float TEXTURE_TILE_SIZE = 1f * 16f / 512f;
	const float CORRECTION = 1f / (512f * 64f);
	Sprite[] interfaceBack = new Sprite[36];
	Sprite[] nonActive = new Sprite[12];
	Sprite useSprite;
	Sprite marker;
	
	Button[] sideButton = new Button[5];
	Button[] backButton = new Button[36];
	int shift = 0;
	int groundShift = 0;
	bool visibility = false;
	
	struct ItemInTable{
		public Item item;
		public int position;
		public bool onGround;
	}
		
	ItemInTable current;
		
	public bool visible {
		get{
			return visibility;
		}
		set{
			if (value != visibility) {
				Show(value);
			}
		}
	}
	
	Sprite CreateSprite(Coordinate tileUV, Vector3 position){		
		return Tile.CreateTile(transform, tileUV, position);
	}
	
	Sprite CreatePart(Rect tileUV, Vector3 position){		
		Sprite tile = Sprite.Create(
			transform, position, 
			new Vector2(tileUV.width * Tile.TILE_SIZE, tileUV.height * Tile.TILE_SIZE), 
			Resources.Load("Material/Main") as Material);
		tile.SetUV(
				new Rect(
				        tileUV.x * TEXTURE_TILE_SIZE + CORRECTION, 
				        tileUV.y * TEXTURE_TILE_SIZE + CORRECTION, 
				        tileUV.width  * TEXTURE_TILE_SIZE - CORRECTION * 2f,
						tileUV.height * TEXTURE_TILE_SIZE - CORRECTION * 2f));
		return tile;
	}
	
	void Awake () {
		instance = this;
	}
	
	void ShowInventory(bool visible) {
		if (Hero.instance != null) {
			if (Hero.instance.inventory != null){
				foreach(Item item in Hero.instance.inventory){
					if (item != null){
						item.Hide();
					}
				}
				if (shift >= Hero.instance.inventory.Length / 5 - 1) {
					shift = Hero.instance.inventory.Length / 5 - 2;
				}
				for (int i = shift * 5; i < Hero.instance.inventory.Length && i < 30 + shift * 5; i++) {
					if (Hero.instance.inventory[i] != null){
						if (visible){
							Hero.instance.inventory[i].ShowIcon(interfaceBack[i - shift * 5].transform, new Vector3(0,0,-1));
						} else {
							Hero.instance.inventory[i].Hide();
						}
					}
				}
			}
			if (Level.instance != null) {
				Item[] items = Level.instance.GetItemsOnCell(Hero.instance.position.x, Hero.instance.position.y);
				if (items != null){
					foreach(Item item in items){
						if (item != null){
							item.Hide();}
					}
					if (groundShift >= items.Length) {
						groundShift = items.Length - 1;
					}
					for (int i = groundShift; i < items.Length &&  i - groundShift + 30 < interfaceBack.Length; i++) {
						if (items[i] != null){
							if (visible){
								items[i].ShowIcon(interfaceBack[i - groundShift + 30].transform, new Vector3(0,0,-1));
							} else {
								items[i].Hide();
							}
						}
					}
				}
			}
		}
	}
	
	ItemInTable getItemOnPosition(int num){		
		ItemInTable selected = new ItemInTable();
		if (num < 30) {
			if (Hero.instance != null) {
				if (Hero.instance.inventory != null){
					if (num + shift * 5 < Hero.instance.inventory.Length){
						selected.item = Hero.instance.inventory[num + shift * 5];
						selected.onGround = false;
						selected.position = num + shift * 5;
					} else {
						Item[] heroItems = new Item[num + shift * 5 + 1];
						for(int i = 0; i < Hero.instance.inventory.Length; i++) {
							heroItems[i] = Hero.instance.inventory[i];
						}
						Hero.instance.inventory = heroItems;
						selected.item = null;
						selected.onGround = false;
						selected.position = num + shift * 5;
					}
				}
			}
		} else {
			if (Level.instance != null) {
				Item[] items = Level.instance.GetItemsOnCell(Hero.instance.position.x, Hero.instance.position.y);
				if (items != null){
					if (num - 30 + groundShift < items.Length) {
						selected.item = items[num - 30 + groundShift];
						selected.onGround = true;
						selected.position = num - 30 + groundShift;	
					} else {
						Item[] groundItems = new Item[num - 30 + groundShift + 1];
						for(int i = 0; i < items.Length; i++) {
							groundItems[i] = items[i];
						}
						Level.instance.SetItemsOnCell(Hero.instance.position.x, Hero.instance.position.y, groundItems);
						selected.item = null;
						selected.onGround = true;
						selected.position = num - 30 + groundShift;
					}
				} else {
					selected.item = null;
					selected.onGround = true;
					selected.position = num - 30 + groundShift;					
				}
			}
		}
		return selected;
	}
	
	void SetValue(ItemInTable item){
		if (Hero.instance != null) {
			if (!item.onGround){
				if (Hero.instance.inventory != null){
					Hero.instance.inventory[item.position] = item.item;
				}		
			} else {
				Item[] items = Level.instance.GetItemsOnCell(Hero.instance.position.x, Hero.instance.position.y);
				if (items == null){
					items = new Item[item.position + 1];
				} 
				items[item.position] = item.item;
				Level.instance.SetItemsOnCell(Hero.instance.position.x, Hero.instance.position.y, items);
			}	
		}
	}
	
	void SelectItem(int num){
//		Debug.Log(num.ToString());
		ItemInTable selected = getItemOnPosition(num);
		
		if (current.item == null) {
			if (selected.item != null){
				current = selected;
				if (current.item.icon != null){
					marker.transform.parent = current.item.icon.transform;
					marker.transform.localPosition = Vector3.zero;
				}
			}
		} else {
			if (selected.item == null){
				selected.item = current.item;
				current.item = null;
				SetValue(selected);
				SetValue(current);
			} else {
				Item temp = selected.item;
				selected.item = current.item;
				current.item = temp;
				SetValue(selected);
				SetValue(current);
			}
			current.item = null;
		}
		ShowInventory(visibility);
		Show(visibility);
	}
	
	void Start () {
		for (int i = 0; i < 30; i++){
			interfaceBack[i] = CreateSprite(new Coordinate(31, 0), new Vector3( i / 5 - 3 + 0.5f, -i % 5 + 3 - 0.5f, -1f) * Tile.TILE_SIZE);
			backButton[i] = Utils.Create<Button>(interfaceBack[i].transform);
			backButton[i].SetSize(new Vector3(Tile.TILE_SIZE, Tile.TILE_SIZE, 1));
			backButton[i].SetReceiverWithTag(SelectItem, i);
		}
		for (int i = 30; i < interfaceBack.Length; i++){
			interfaceBack[i] = CreateSprite(new Coordinate(30, 0), new Vector3( i % 6 - 3 + 0.5f, -i / 6 + 3 - 0.5f, -1f) * Tile.TILE_SIZE);
			backButton[i] = Utils.Create<Button>(interfaceBack[i].transform);
			backButton[i].SetSize(new Vector3(Tile.TILE_SIZE, Tile.TILE_SIZE, 1));
			backButton[i].SetReceiverWithTag(SelectItem, i);
		}
		//top arrows
		nonActive[0] = CreatePart(new Rect(31,    1, 0.5f, 1), new Vector3(-3.25f, 0.5f, -1f) * Tile.TILE_SIZE);
		nonActive[1] = CreatePart(new Rect(31.5f, 1, 0.5f, 1), new Vector3( 3.25f, 0.5f, -1f) * Tile.TILE_SIZE);
		//bottom arrows
		nonActive[2] = CreatePart(new Rect(30,    1, 0.5f, 1), new Vector3(-3.25f, -2.5f, -1f) * Tile.TILE_SIZE);
		nonActive[3] = CreatePart(new Rect(30.5f, 1, 0.5f, 1), new Vector3( 3.25f, -2.5f, -1f) * Tile.TILE_SIZE);
		//decor
		nonActive[4] = CreatePart(new Rect(31,    2, 0.5f, 1), new Vector3(-3.25f,-0.5f, -1f) * Tile.TILE_SIZE);
		nonActive[5] = CreatePart(new Rect(31.5f, 2, 0.5f, 1), new Vector3( 3.25f,-0.5f, -1f) * Tile.TILE_SIZE);
		nonActive[6] = CreatePart(new Rect(31,    2, 0.5f, 1), new Vector3(-3.25f,-1.5f, -1f) * Tile.TILE_SIZE);
		nonActive[7] = CreatePart(new Rect(31.5f, 2, 0.5f, 1), new Vector3( 3.25f,-1.5f, -1f) * Tile.TILE_SIZE);
		nonActive[8] = CreatePart(new Rect(31,    2, 0.5f, 1), new Vector3(-3.25f, 1.5f, -1f) * Tile.TILE_SIZE);
		nonActive[9] = CreatePart(new Rect(31.5f, 2, 0.5f, 1), new Vector3( 3.25f, 1.5f, -1f) * Tile.TILE_SIZE);
		nonActive[10] = CreatePart(new Rect(31,    2, 0.5f, 1), new Vector3(-3.25f, 2.5f, -1f) * Tile.TILE_SIZE);
		nonActive[11] = CreatePart(new Rect(31.5f, 2, 0.5f, 1), new Vector3( 3.25f, 2.5f, -1f) * Tile.TILE_SIZE);
		useSprite = CreatePart(new Rect(31,    3, 0.5f, 1), new Vector3(-3.25f, 2.5f, -1.5f) * Tile.TILE_SIZE);
		marker = Tile.CreateChar(transform, new Coordinate(0, 0), Vector3.zero);
		
		sideButton[0] = Utils.Create<Button>(nonActive[0].transform);
		sideButton[0].SetSize(new Vector3(Tile.TILE_SIZE * 0.5f, Tile.TILE_SIZE, 1));
		sideButton[0].SetReceiver(delegate() {
			shift --;
			if (shift < 0) {
				shift = 0;}
			ShowInventory(true);
			Show(true);
		});
		sideButton[1] = Utils.Create<Button>(nonActive[1].transform);
		sideButton[1].SetSize(new Vector3(Tile.TILE_SIZE * 0.5f, Tile.TILE_SIZE, 1));
		sideButton[1].SetReceiver(delegate() {
			shift ++;
			ShowInventory(true);
			Show(true);
		});
		sideButton[2] = Utils.Create<Button>(nonActive[2].transform);
		sideButton[2].SetSize(new Vector3(Tile.TILE_SIZE * 0.5f, Tile.TILE_SIZE, 1));
		sideButton[2].SetReceiver(delegate() {
			groundShift --;
			if (groundShift < 0) {
				groundShift = 0;}
			ShowInventory(true);
			Show(true);
		});
		sideButton[3] = Utils.Create<Button>(nonActive[3].transform);
		sideButton[3].SetSize(new Vector3(Tile.TILE_SIZE * 0.5f, Tile.TILE_SIZE, 1));
		sideButton[3].SetReceiver(delegate() {
			groundShift ++;
			ShowInventory(true);
		});
		sideButton[4] = Utils.Create<Button>(nonActive[10].transform);
		sideButton[4].SetSize(new Vector3(Tile.TILE_SIZE * 0.5f, Tile.TILE_SIZE, 1));
		sideButton[4].SetReceiver(delegate() {
			Debug.Log("Use");
			if (current.item != null){
				if (current.item.Use()){
					current.item.Hide();
					current.item = null;
					SetValue(current);
				}
			}
		});
		
		Show(visibility);
	}
	
	public void Show(bool visible) {
		foreach(Sprite sprite in interfaceBack) {
			if (sprite != null){
				sprite.visible = visible; }	}
		foreach(Sprite sprite in nonActive) {
			if (sprite != null){
				sprite.visible = visible;}	}
		foreach(Button button in sideButton) {
			if (button != null){
				button.visible = visible;}	}
		if (useSprite != null)
			useSprite.visible = (current.item != null) && visible;
		if (marker != null){
			if (current.item != null){
				if (current.item.icon != null) {
					marker.visible = (current.item.icon.visible) && visible;
				} else {
					marker.visible = false;}
			} else {
				marker.visible = false;	}
		}
		visibility = visible;
		ShowInventory(visibility);
	}
	
	void Update () {
	
	}
}
