using System;
using System.Collections.Generic;
using NUnit.Framework;
using Unity.VisualScripting;

namespace DungeonGenerator
{
    public enum RoomSide
    {
        Top,
        Bottom,
        Left,
        Right
    }
    public enum RoomType
    {
        Normal,
        Entrance,
        Monster,
        Boss
    }
    
    public class Room
    {
        public Room(RoomType roomType, int width, int height, Point positionOfTopLeft)
        {
            TypeOfRoom = roomType;
            Width = width;
            Height = height;
            PositionOfTopLeft = positionOfTopLeft;
        }

        private readonly Dictionary<RoomSide, List<Room>> _adjacentRooms = new();

        public RoomType TypeOfRoom { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
        public Point PositionOfTopLeft { get; set; }

        public List<Point> GetPointsInRoom()
        {
            List<Point> points = new List<Point>();
            for (int i = 0; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    points.Add(new Point(PositionOfTopLeft.X + i, PositionOfTopLeft.Y + j));
                }
            }

            return points;
        }

        public int GetDistanceToRoom(Room other)
        {
            Point centerOfRoom = GetCenterOfRoom();
            Point centerOfOther = other.GetCenterOfRoom();
            return centerOfRoom.ManhattanDistance(centerOfOther);
        }

        public Point GetCenterOfRoom()
        {
            return new Point(PositionOfTopLeft.X + Width / 2, PositionOfTopLeft.Y + Height / 2);
        }
        
        public void AddAdjacentRoom(Room room, RoomSide side)
        {
            if (!_adjacentRooms.ContainsKey(side))
            {
                _adjacentRooms[side] = new List<Room>();
            }

            // Prevent duplicates
            if (!_adjacentRooms[side].Contains(room))
            {
                _adjacentRooms[side].Add(room);
                room.AddAdjacentRoom(this, GetOppositeSide(side)); // Ensure bidirectional linkage
            }
        }

        // Helper method to get the opposite side
        private RoomSide GetOppositeSide(RoomSide side) => side switch
        {
            RoomSide.Top => RoomSide.Bottom,
            RoomSide.Bottom => RoomSide.Top,
            RoomSide.Left => RoomSide.Right,
            RoomSide.Right => RoomSide.Left,
            _ => throw new ArgumentException("Invalid RoomSide", nameof(side))
        };
    }
}