/// <summary>
    /// Removes the room from the overall dictionary, sets all door parents and destroys the room object
    /// </summary>
    /// <param name="room">Room to destroy</param>
    /// <param name="roomId">Unique ID of the room</param>
    private void HandleRoomDespawning(BaseRoom room, Guid roomId)
    {
        // Remove the room from overall dictionary
        roomDictionary.Remove(roomId);

        Dictionary <Vector2, RoomDoor>  roomDoors        = room.roomDoors;
        Dictionary <RoomDoor, BaseRoom> neighboringRooms = new Dictionary <RoomDoor, BaseRoom>();

        // Enumerate through the room's doors
        foreach (KeyValuePair <Vector2, RoomDoor> kvp in roomDoors)
        {
            RoomDoor door = kvp.Value;

            Vector2 doorExit = room.GetDoorExit(door);

            // Skip doors that don't have another room connected
            if (!roomLocations.ContainsKey(doorExit))
            {
                continue;
            }

            BaseRoom exitRoom = roomLocations[doorExit];

            neighboringRooms.Add(door, exitRoom);
        }

        // Enumerate through all doors
        foreach (KeyValuePair <RoomDoor, BaseRoom> kvp in neighboringRooms)
        {
            BaseRoom neighboringRoom = kvp.Value;

            if (neighboringRoom == null)
            {
                continue;
            }

            RoomDoor currentDoor = kvp.Key;

            Vector2 setLocation = currentDoor.GetLocation();

            // Change connected door's parent to their other connected room so they don't get destroyed
            currentDoor.transform.SetParent(neighboringRoom.transform);
        }

        // Loop through all the tile locations for the room to be destroyed
        for (int i = 0; i < room.roomLocations.Count; ++i)
        {
            Vector2 location = room.roomLocations[i];
            if (roomLocations.ContainsKey(location))
            {
                // Remove the tile location from the overall used locations
                roomLocations.Remove(location);
            }
        }

        // Finally destroy the room object
        Destroy(room.gameObject);
    }
    /// <summary>
    /// Creates a single room that should be connected to the given door
    /// </summary>
    /// <param name="door"></param>
    private static void CreateRoom(RoomDoor door, BaseRoom connectedRoom)
    {
        if (door == null || connectedRoom == null)
        {
            Debug.LogError("Given door or room is null!");
            return;
        }

        Vector2 doorExit = connectedRoom.GetDoorExit(door);
        // Get the first tile locations to start the recursive operation
        List <Vector2> firstTileLocations = GetOpenNeighboringTiles(doorExit);

        List <Vector2> roomTiles = new List <Vector2>
        {
            doorExit
        };

        UnityEngine.Random.InitState((int)DateTime.UtcNow.Ticks);

        // Loop through the first locations and start creating tiles
        foreach (Vector2 pos in firstTileLocations)
        {
            float cumulativeChance = Instance.additionalTileChance;

            roomTiles = RandomRoomLayoutRecursive(roomTiles, cumulativeChance, pos);
        }

        // When all room tiles have been found, instantiate the object
        BaseRoom newRoom = Instantiate(Instance?.baseRoomPrefab);

        newRoom.roomLocations = roomTiles;
        // Initialize the room after instantiation
        newRoom.InitRoom(door);

        door.connectedRooms[doorExit] = newRoom;

        PlaceRoom(newRoom);
    }
    /// <summary>
    /// Creates adjacent rooms to the given room
    /// </summary>
    /// <param name="room"></param>
    internal static void CreateConnectedRooms(BaseRoom room)
    {
        if (room == null)
        {
            Debug.LogError("Given room is null!");
            return;
        }

        if (Instance == null || Instance.baseRoomPrefab == null)
        {
            Debug.LogError("Instance or room prefab is null!");
            return;
        }

        // Enumerate through the room's doors
        foreach (KeyValuePair <Vector2, RoomDoor> kvp in room.roomDoors)
        {
            Vector2 doorExit = room.GetDoorExit(kvp.Value);
            // If there's already a room on the other side of the door, skip and add that room to the door's info
            if (roomLocations.ContainsKey(doorExit) && doorExit != Vector2.zero)
            {
                BaseRoom exitRoom = roomLocations[doorExit];

                kvp.Value.connectedRooms[doorExit] = exitRoom;

                if (!exitRoom.roomDoors.ContainsKey(kvp.Key))
                {
                    exitRoom.roomDoors.Add(kvp.Key, kvp.Value);
                }

                continue;
            }

            CreateRoom(kvp.Value, room);
        }
    }
    /// <summary>
    /// Creates doors for the first room
    /// </summary>
    private void CreateRoomDoors(RoomDoor createdFromDoor, BaseRoom room)
    {
        if (room == null)
        {
            return;
        }

        // Ignore restrictions for the first room
        bool ignoreRestrictions = createdFromDoor == null;

        List <Vector2> possibleDirections = new List <Vector2>
        {
            Vector2.left,
            Vector2.right,
            Vector2.up,
            Vector2.down
        };

        List <Vector2> directions = new List <Vector2>();

        if (!ignoreRestrictions)
        {
            // Find furthest tiles in all directions except current door direction
            Vector2 excludedDirection = room.GetDoorExit(createdFromDoor) - room.GetDoorEntrance(createdFromDoor);

            possibleDirections.Remove(excludedDirection);

            for (int i = 0; i < Instance?.doorAmountPerRoom; ++i)
            {
                int randomNumber = UnityEngine.Random.Range(0, possibleDirections.Count);

                directions.Add(possibleDirections[randomNumber]);
                possibleDirections.RemoveAt(randomNumber);
            }
        }
        else
        {
            directions = possibleDirections;
        }

        for (int i = 0; i < directions.Count; ++i)
        {
            Vector2 direction = directions[i];

            Vector2 doorLocation = room.FindFurthestTileInDirection(direction);

            // Skip if no eligible location was found
            if (doorLocation == Vector2.zero)
            {
                continue;
            }

            Vector2 setLocation = doorLocation + (direction * 0.5f);

            if (roomLocations.ContainsKey(doorLocation + direction))
            {
                // Disabled creating new doors to old rooms for now
                continue;

                //BaseRoom room = RoomGenerator.roomLocations[doorLocation + direction];
                //if (room.roomWalls.ContainsKey(setLocation))
                //{
                //    GameObject destroyWall = room.roomWalls[setLocation];
                //    room.roomWalls.Remove(setLocation);
                //    Destroy(destroyWall);
                //}
            }

            RoomDoor newDoor = Instantiate(Instance?.roomDoorPrefab, room.transform);
            newDoor.transform.position  = setLocation;
            newDoor.transform.position += new Vector3(0, 0, -5);
            newDoor.transform.rotation  = Quaternion.Euler(0, 0, (direction.y != 0 ? 90 : 0));
            newDoor.connectedRooms.Add(doorLocation, room);
            newDoor.connectedRooms.Add(doorLocation + direction, null);
            room.roomDoors.Add(setLocation, newDoor);
        }
    }