using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Utilities;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;

namespace EscapeRoomEngine.Engine.Runtime
{
    /// <summary>
    /// The passage handles the two door modules that connect two spaces.
    /// </summary>
    public class Passage
    {
        /// <summary>
        /// The exit door in the previous room.
        /// </summary>
        internal readonly DoorModule fromOut;
        /// <summary>
        /// The entrance door in the next room.
        /// </summary>
        internal DoorModule toIn;

        internal Passage(DoorModule from)
        {
            if (!from.IsExit && !from.description.Equals(Engine.Theme.spawnDoor))
            {
                throw new WrongTypeException(DoorType.Exit, DoorType.Entrance);
            }
            
            fromOut = from;
        }

        /// <summary>
        /// Place an entrance door in the same position relative to the room origin as the exit door.
        /// </summary>
        internal void PlaceEntrance(DoorModule door)
        {
            if (!door.IsEntrance)
            {
                throw new WrongTypeException(DoorType.Entrance, DoorType.Exit);
            }
            
            toIn = door;
            
            // to make sure the origin of the player doesn't move, the two doors must be placed in the same location in the same orientation
            toIn.PlaceRoomRelative(fromOut.RrPosition, fromOut.Orientation);
            
            Logger.Log($"Placed entrance {toIn} at {toIn.RrPosition} (RR)", LogType.ModulePlacement);
        }

        /// <summary>
        /// Connect the two doors in this passage.
        /// </summary>
        internal void ConnectDoors()
        {
            toIn.Passage = this;
            fromOut.Passage = this;
            
            Logger.Log($"Connected passage from {fromOut} to {toIn}", LogType.PassageConnection);
        }

        /// <summary>
        /// Return the door connected to a given door in this passage.
        /// </summary>
        internal DoorModule Other(DoorModule of)
        {
            if (of.Equals(fromOut))
            {
                return toIn;
            }
            if(of.Equals(toIn))
            {
                return fromOut;
            }

            throw new EngineException($"{of} is not connected to this passage");
        }
    }
}