using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using Unity.VisualScripting.FullSerializer;
using UnityEngine;
using GameObject = UnityEngine.GameObject;

public class LevelManager : MonoBehaviour
{
    public int width = 20;
    public int height = 20;
    public int maxRooms = 15; // Maximum number of rooms to generate
    public List<GameObject> room1DPrefabs;
    public List<GameObject> room2DPrefabs;
    public List<GameObject> room3DPrefabs;
    public List<GameObject> room4DPrefabs;

    private int[,] grid;
    private System.Random rng = new System.Random();
    private int roomCount = 0; // Counter for the number of rooms created
    private List<Vector2> rooms = new List<Vector2>();
    
    void Start()
    {
        grid = new int[width, height];
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                grid[i, j] = 0;
            }
        }
        
        grid[(int)(width / 2), (int)(height / 2)] = 1;
        rooms.Add(new Vector2((int)(width / 2), (int)(height / 2)));
        
        GenerateDungeon(maxRooms);
        RenderDungeon();
    }

    void GenerateDungeon(int maxRooms)
    {
        int roomId = 0;
        int iteration = 0;
        while (rooms.Count < maxRooms && iteration <= 1000)
        {
            iteration++;
            for (int r = 0; r < 4; r++)
            {
                int posX = (int)rooms[roomId].x;
                int posY = (int)rooms[roomId].y;

                switch (r)
                {
                    case 0: if (posX + 1 < grid.GetLength(0)) RoomCheck(posX + 1, posY); break;
                    case 1: if (posX - 1 >= 0) RoomCheck(posX - 1, posY); break;
                    case 2: if (posY + 1 < grid.GetLength(1)) RoomCheck(posX, posY + 1); break;
                    case 3: if (posY - 1 >= 0) RoomCheck(posX, posY - 1); break;
                }

                if (rooms.Count >= maxRooms)
                {
                    break;
                }
            }

            roomId = (roomId + 1) % rooms.Count;
        }

        if (iteration > 1000)
        {
            Debug.LogError("Maximum iterations reached.");
        }
    }

    void RoomCheck(int posX, int posY)
    {
        if (grid[posX, posY] == 1 || Random.Range(0, 2) == 1)
        {
            return;
        }

        int occupiedRoomCount = 0;

        if (posX + 1 < grid.GetLength(0))
            occupiedRoomCount += grid[posX + 1, posY];
        if (posX - 1 >= 0)
            occupiedRoomCount += grid[posX - 1, posY];
        if (posY + 1 < grid.GetLength(1)) 
            occupiedRoomCount += grid[posX, posY + 1];
        if (posY - 1 >= 0)
            occupiedRoomCount += grid[posX, posY - 1];

        if (occupiedRoomCount > 1)
        {
            return;
        }

        grid[posX, posY] = 1;
        rooms.Add(new Vector2(posX, posY));
    }


    void RenderDungeon()
    {
        string dungeon = "";
        
        for (int x = 0; x < width; x++)
        {
            for (int y = 0; y < height; y++)
            {
                dungeon  += grid[x, y];
                if (grid[x, y] == 1)
                {
                    string room="";
                    if ((y - 1 >= 0) && (grid[x, y-1] == 1))
                    {
                        room += "u";
                    }
                    if ((y + 1 < grid.GetLength(1)) && (grid[x, y+1] == 1)) 
                    {
                        room += "d";
                    }
                    if ((x + 1 < grid.GetLength(0)) && (grid[x+1, y] == 1))
                    {
                        room += "l";
                    }
                    if ((x - 1 >= 0) && (grid[x-1, y] == 1))
                    {
                        room += "r";
                    }
                    
                    AddRoom(room, room.Length, new Vector2(x, y));
                }
            }

            dungeon += "\n";
        }
        print(dungeon);
    }

    void AddRoom(string roomName, int roomDimension, Vector2 roomPosition)
    {
        List<GameObject> roomPrefabs = null;
        switch (roomDimension)
        {
            case 1:
                roomPrefabs = room1DPrefabs;
                break;
            case 2:
                roomPrefabs = room2DPrefabs;
                break;
            case 3:
                roomPrefabs = room3DPrefabs;
                break;
            case 4:
                roomPrefabs = room4DPrefabs;
                break;
            default:
                return;
        }
        
        for (int i = 0; i < roomPrefabs.Count; i++)
        {
            if (roomPrefabs[i].name == roomName+"-base")
            {
                float  xMult = roomPrefabs[i].GetComponent<Renderer>().bounds.extents.x*2;
                float  yMult = roomPrefabs[i].GetComponent<Renderer>().bounds.extents.z*2;
                Instantiate(roomPrefabs[i], new Vector3((roomPosition.x - (int)width / 2)*xMult, 0f, (roomPosition.y - (int)height / 2)*yMult), Quaternion.Euler(0f, 0f, 0f));
                break;
            }
        }
    }
}