using Godot;
using System;
using System.Collections.Generic;

public partial class Map : PanelContainer
{
	[Export] GridContainer grid;
	private HashSet<Tile> handledTiles = new HashSet<Tile>();
	private Dictionary<Tile, TextureRect> textureMap = new Dictionary<Tile, TextureRect>();

	public override void _Ready()
	{
		grid.Columns = GameData.layerSize + 1;
	}

	public void ShowMap()
	{
		if (!Visible) return;

		ClearGrid();

		Tile[,] tiles = GameData.map[GameData.currentLayer].tiles;
		int size = GameData.layerSize;

		for (int z = -1; z < size; z++)
		{
			for (int x = -1; x < size; x++)
			{
				if (z == -1 || x == -1)
				{
					grid.AddChild(CreateHeaderLabel(x, z));
					continue;
				}

				TextureRect texture = CreateTileTexture(tiles[x, z]);
				textureMap[tiles[x, z]] = texture;

				if (!handledTiles.Contains(tiles[x, z]))
				{
					tiles[x, z].OnTileVisited += OnTileVisited;
					handledTiles.Add(tiles[x, z]);
				}

				texture.SizeFlagsHorizontal = SizeFlags.ExpandFill;
				texture.SizeFlagsVertical = SizeFlags.ExpandFill;
				texture.StretchMode = TextureRect.StretchModeEnum.Scale;

				grid.AddChild(texture);
			}
		}
	}

	private void ClearGrid()
	{
		foreach (Node node in grid.GetChildren())
		{
			grid.RemoveChild(node);
			node.QueueFree();
		}
	}

	private Label CreateHeaderLabel(int x, int z)
	{
		Label label = new Label
		{
			HorizontalAlignment = HorizontalAlignment.Center,
			VerticalAlignment = VerticalAlignment.Center,
			SizeFlagsHorizontal = SizeFlags.ExpandFill,
			SizeFlagsVertical = SizeFlags.ExpandFill
		};

		if (z == -1 && x == -1) label.Text = "\u2193 Z | \u2192 X";
		else if (z == -1) label.Text = x.ToString();
		else label.Text = z.ToString();

		return label;
	}

	private TextureRect CreateTileTexture(Tile tile)
	{
		TextureRect texture = new TextureRect
		{
			SizeFlagsHorizontal = SizeFlags.ExpandFill,
			SizeFlagsVertical = SizeFlags.ExpandFill,
			StretchMode = TextureRect.StretchModeEnum.Scale
		};

		UpdateTileTexture(tile, texture);
		return texture;
	}

	private void OnTileVisited(object sender, EventArgs e)
	{
		Tile tile = sender as Tile;

		if (tile == null)
			return;

		if (textureMap.TryGetValue(tile, out TextureRect texture))
		{
			UpdateMap(tile, texture);
		}
	}

	public void UpdateMap(Tile tile, TextureRect texture)
	{
		if (!IsInstanceValid(texture)) return;

		UpdateTileTexture(tile, texture);
	}

	private void UpdateTileTexture(Tile tile, TextureRect texture)
	{
		if (!tile.wasVisited && !GameData.debugMode)
		{
			texture.Texture = GenerateTexture(32, new Color(0, 0, 0, 1));
			texture.TooltipText = "Not explored";
		}
		else if (tile.containsResource)
		{
			texture.Texture = ResourceDistributor.resources[tile.resource.name];
			texture.TooltipText = tile.resource.item.GetReadableName() + $"\r(X: {tile.GridPosition.X},Y: {GameData.currentLayer},Z: {tile.GridPosition.Y})";
		}
		else
		{
			texture.Texture = GenerateTexture(32, new Color(0, 0, 0, 0));
			texture.TooltipText = "";
		}
	}

	public Texture2D GenerateTexture(int size, Color fillColor)
	{
		Image image = Image.CreateEmpty(size, size, false, Image.Format.Rgba8);
		image.Fill(fillColor);

		return ImageTexture.CreateFromImage(image);
	}
}
