using UnityEngine;

/// <summary>
/// Чистые данные чанка — без MonoBehaviour, без Unity-объектов.
/// Легко сериализовать, передать в генератор, сохранить на диск.
/// </summary>
public class ChunkData
{
    public const int SIZE = 16; // блоков по X и Z
    public const int HEIGHT = 16; // блоков по Y

    public readonly Vector3Int ChunkPos; // позиция чанка в чанковых координатах

    // null = пустой блок, иначе blockId
    private readonly string[,,] _blocks = new string[SIZE, HEIGHT, SIZE];

    public bool IsDirty { get; private set; } = true; // нужен ли пересчёт меша

    public ChunkData(Vector3Int chunkPos)
    {
        ChunkPos = chunkPos;
    }

    /// <summary>Получить blockId по локальным координатам. null = пусто.</summary>
    public string GetBlock(int x, int y, int z)
    {
        if (!InBounds(x, y, z)) return null;
        return _blocks[x, y, z];
    }

    public string GetBlock(Vector3Int local) => GetBlock(local.x, local.y, local.z);

    /// <summary>Установить блок. null = удалить.</summary>
    public void SetBlock(int x, int y, int z, string blockId)
    {
        if (!InBounds(x, y, z)) return;
        _blocks[x, y, z] = blockId;
        IsDirty = true;
    }

    public void SetBlock(Vector3Int local, string blockId) =>
        SetBlock(local.x, local.y, local.z, blockId);

    public void ClearDirty() => IsDirty = false;

    public static bool InBounds(int x, int y, int z) =>
        x >= 0 && x < SIZE &&
        y >= 0 && y < HEIGHT &&
        z >= 0 && z < SIZE;

    /// <summary>
    /// Перевод мировой позиции блока → позиция чанка (чанковые координаты).
    /// </summary>
    public static Vector3Int WorldToChunkPos(Vector3Int worldBlock) =>
        new Vector3Int(
            Mathf.FloorToInt((float)worldBlock.x / SIZE),
            Mathf.FloorToInt((float)worldBlock.y / HEIGHT),
            Mathf.FloorToInt((float)worldBlock.z / SIZE));

    /// <summary>
    /// Перевод мировой позиции блока → локальная позиция внутри чанка.
    /// </summary>
    public static Vector3Int WorldToLocal(Vector3Int worldBlock)
    {
        int x = worldBlock.x % SIZE;
        int y = worldBlock.y % HEIGHT;
        int z = worldBlock.z % SIZE;
        // Обработка отрицательных координат
        if (x < 0) x += SIZE;
        if (y < 0) y += HEIGHT;
        if (z < 0) z += SIZE;
        return new Vector3Int(x, y, z);
    }

    /// <summary>Позиция чанка → мировая позиция его нижнего-левого угла.</summary>
    public static Vector3Int ChunkToWorld(Vector3Int chunkPos) =>
        new Vector3Int(chunkPos.x * SIZE, chunkPos.y * HEIGHT, chunkPos.z * SIZE);
}
