using System.Collections.Generic;
using System.Linq;
using EscapeRoomEngine.Engine.Runtime.Measurements;
using EscapeRoomEngine.Engine.Runtime.Modules;
using EscapeRoomEngine.Engine.Runtime.Modules.Description;
using EscapeRoomEngine.Engine.Runtime.Modules.State;
using UnityEngine;
using Logger = EscapeRoomEngine.Engine.Runtime.Utilities.Logger;
using LogType = EscapeRoomEngine.Engine.Runtime.Utilities.LogType;
namespace EscapeRoomEngine.Engine.Runtime
{
///
/// A room manages an entrance to its first space and exit from its last space. It is also responsible for instantiating all spaces in it.
///
public class Room
{
internal Passage entrance, exit;
internal GameObject roomObject;
internal readonly List puzzles = new();
///
/// Return whether this room is the last room of the experience, determined by whether this room has an exit.
///
internal bool LastRoom => exit == null;
private readonly List _spaces = new();
private readonly List _doors = new();
internal Room(Passage entrance)
{
this.entrance = entrance;
}
internal void AddSpace(Space space, Passage spaceExit)
{
_spaces.Add(space);
exit = spaceExit;
}
///
/// Solves all puzzles in this room.
///
public void SkipRoom()
{
Logger.Log($"Skipping {this}...", LogType.PuzzleFlow);
puzzles.ForEach(puzzle => puzzle.PuzzleState.Solve());
if (puzzles.Count == 0 && !LastRoom)
{
exit.fromOut.DoorState.Unlock();
}
}
public void EnterRoom()
{
entrance.toIn.DoorState.ExitFrom();
}
internal void AddPuzzle(PuzzleModule puzzle)
{
puzzles.Add(puzzle);
puzzle.PuzzleState.PuzzleEvent += OnPuzzleEvent;
}
private void OnPuzzleEvent(PuzzleModule puzzle, PuzzleEventType type)
{
if (type == PuzzleEventType.Solved)
{
Measure.Solve((PuzzleModuleDescription)puzzle.description);
if (puzzles.All(p => p.PuzzleState.Solved))
{
exit.fromOut.DoorState.Unlock();
}
}
}
internal void AddDoor(DoorModule door)
{
_doors.Add(door);
door.DoorState.DoorEvent += (_, type) =>
{
// ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
switch (type)
{
// generate a new room as soon as the player completes all puzzles in this one
case DoorEventType.Unlocked when !LastRoom && door.Equals(exit.fromOut):
Engine.Instance.GenerateRoom();
break;
// start measurements on every puzzle as soon as the player enters the last room
case DoorEventType.ExitedFrom when door.Equals(entrance.toIn) && Engine.Instance.CurrentRoom.Contains(this):
puzzles.ForEach(puzzle => Measure.StartMeasuring((PuzzleModuleDescription)puzzle.description));
// Engine.Instance.HidePreviousRoom();
break;
}
};
}
internal void InstantiateRoom(Transform parent, Vector3 offset, string name)
{
roomObject = new GameObject($"Room {name}");
roomObject.transform.SetParent(parent, false);
roomObject.transform.localPosition = offset;
for (var i = 0; i < _spaces.Count; i++)
{
_spaces[i].InstantiateSpace(roomObject.transform, i.ToString());
}
entrance.ConnectDoors();
entrance.toIn.DoorState.Unlock();
}
public override string ToString()
{
return roomObject.name;
}
}
}