using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class TileMatrix
{

	public Level Level;
	public Dictionary<string, Tile> Tiles = new();

	private List<Index> Neighbors = new List<Index>()
	{
		new Index(1, 0),
        new Index(-1, 0),
        new Index(0, 1),
        new Index(0, -1),
        new Index(1, -1),
        new Index(1, 1),
        new Index(-1, -1),
        new Index(-1, 1),
    };

	public TileMatrix()
	{

	}

	public void Initialize(Level level, Transform startTile)
	{
        Level = level;
        var tile = new Tile(new Index(0, 0), startTile, startTile.position.y);
        Register(tile);
	}

	public void Update()
	{
		foreach (var tile in Tiles.Values)
			tile.Update();
	}

	public void AddRandomTile()
	{
		var index = GetRandomFreeTileIndex();
		var r = Global.Rng.NextDouble();
		var tileObject = Level.InstantiateTile(index, r <= 0.1d ? Global.BIOME_DIRT : Global.BIOME_GRASS);
        var tile = new Tile(index, tileObject.transform, Random.Range(0, 20));
		Register(tile);
    }

	private void Register(Tile tile)
	{
		Tiles.Add(tile.Index.Identifier, tile);
		var monolith = Object.Instantiate(
			Level.GetComponent<Level>().MonolithTemplate,
			Global.GetRandomPositionOnTile(tile, 8.5f),
			Quaternion.Euler(0, Random.Range(0, 360), 0),
			tile.Element);
        Level.ResourceSpawner.GetComponent<ResourceSpawner>().SpawnOnTile(tile, Global.NODE_INITIAL_COUNT);
	}

	public Tile Get(string identifier)
	{
		if (Tiles.TryGetValue(identifier, out Tile result))
			return result;
		return null;
	}

    public Tile Get(int indexX, int indexY)
    {
        if (Tiles.TryGetValue($"{indexX}-{indexY}", out Tile result))
            return result;
        return null;
    }

	public Index GetRandomFreeTileIndex()
	{
		/*var index = new Index(0, 0);
		var directionX = (Random.Range(0, 2) == 0 ? -1 : 1);
        var directionY = (Random.Range(0, 2) == 0 ? -1 : 1);
        while (Tiles.ContainsKey(index.Identifier))
		{
			var axis = Random.Range(0, 2);
			if (axis == 0)
				index.X += directionX;
			else if (axis == 1)
				index.Y += directionY;
		}
		return index;*/
		var index = GetPlayerPositionIndex();
		var distance = 1;
		while (true)
		{
			Neighbors = (List<Index>)Global.Shuffle(Neighbors);
            foreach (var neighbor in Neighbors)
			{
				index.X += distance * neighbor.X;
				index.Y += distance * neighbor.Y;
				if (!Tiles.ContainsKey(index.Identifier))
					return index;
			}
			distance++;
		}
	}

	public void Remove(GameObject node)
	{
		var index = Global.PositionToIndex(node.transform.position);
		var tile = Get(index.Identifier);
		tile.Remove(node);
	}

	public Index GetPlayerPositionIndex()
	{
		return Global.PositionToIndex(Level.Player.transform.position);
    }

}
