using BriarQueen.Data.Identifiers; using BriarQueen.Framework.Events.UI; using BriarQueen.Framework.Managers.Levels.Data; using BriarQueen.Framework.Managers.Player.Data; using BriarQueen.Framework.Managers.UI; using Cysharp.Threading.Tasks; using UnityEngine; using UnityEngine.UI; namespace BriarQueen.Game.Puzzles.ChapterOne.LaxleyHouse.Clock { public class LaxleyClockFace : BaseItem { [Header("Hands")] [SerializeField] private LaxleyClockHand _hourHand; [SerializeField] private LaxleyClockHand _minuteHand; [SerializeField] private Image _hub; private LaxleyClockBasePuzzle _owningPuzzle; private bool _locked; public bool HourHandPlaced => _hourHand != null && _hourHand.Placed; public bool MinuteHandPlaced => _minuteHand != null && _minuteHand.Placed; public int HourHandRotationStep => _hourHand != null ? _hourHand.CurrentRotationStep : 0; public int MinuteHandRotationStep => _minuteHand != null ? _minuteHand.CurrentRotationStep : 0; public override string InteractableName => "Clock Face"; public override UICursorService.CursorStyle ApplicableCursorStyle => UICursorService.CursorStyle.Interact; public void Initialise(LaxleyClockBasePuzzle owningPuzzle) { _owningPuzzle = owningPuzzle; _locked = false; gameObject.SetActive(true); if (_hub != null) _hub.gameObject.SetActive(true); _hourHand?.Initialise(this, _owningPuzzle); _minuteHand?.Initialise(this, _owningPuzzle); RefreshInteractionState(); } public override async UniTask OnInteract(ItemDataSo item = null) { if (!IsInteractable()) return; if (item == null) { string message = string.Empty; if (!HourHandPlaced && !MinuteHandPlaced) { message = InteractEventIDs.Get(EnvironmentInteractKey.LaxleyGrandfatherClockMissingBothHands); } else if (!HourHandPlaced && MinuteHandPlaced) { message = InteractEventIDs.Get(EnvironmentInteractKey.LaxleyGrandfatherClockMissingHourHand); } else if (HourHandPlaced && !MinuteHandPlaced) { message = InteractEventIDs.Get(EnvironmentInteractKey.LaxleyGrandfatherClockMissingMinuteHand); } if (!string.IsNullOrWhiteSpace(message)) EventCoordinator.Publish(new DisplayInteractEvent(message)); return; } bool isHourHandItem = item.UniqueID == ItemIDs.Get(ItemKey.LaxleyClockHourHand); bool isMinuteHandItem = item.UniqueID == ItemIDs.Get(ItemKey.LaxleyClockMinuteHand); if (!isHourHandItem && !isMinuteHandItem) { EventCoordinator.Publish(new DisplayInteractEvent(InteractEventIDs.Get(ItemInteractKey.CantUseItem))); return; } await PlaceHand(item); } public bool AreBothHandsPlaced() { return HourHandPlaced && MinuteHandPlaced; } public void LockHands() { _locked = true; _hourHand?.Lock(); _minuteHand?.Lock(); RefreshInteractionState(); } public void HideMechanism() { _locked = true; _hourHand?.Hide(); _minuteHand?.Hide(); if (_hub != null) _hub.gameObject.SetActive(false); gameObject.SetActive(false); } public void RestoreState( bool hourPlaced, bool minutePlaced, int hourRotationStep, int minuteRotationStep, bool solved) { _locked = solved; gameObject.SetActive(!solved); if (solved) { _hourHand?.RestoreState(hourPlaced, hourRotationStep, true); _minuteHand?.RestoreState(minutePlaced, minuteRotationStep, true); HideMechanism(); return; } if (_hub != null) _hub.gameObject.SetActive(true); _hourHand?.RestoreState(hourPlaced, hourRotationStep, false); _minuteHand?.RestoreState(minutePlaced, minuteRotationStep, false); RefreshInteractionState(); } internal async UniTask NotifyHandChanged() { RefreshInteractionState(); if (_owningPuzzle != null) await _owningPuzzle.NotifyClockStateChanged(); } private async UniTask PlaceHand(ItemDataSo item) { if (item.UniqueID == ItemIDs.Get(ItemKey.LaxleyClockHourHand)) { await _hourHand.Place(); } else if (item.UniqueID == ItemIDs.Get(ItemKey.LaxleyClockMinuteHand)) { await _minuteHand.Place(); } PlayerManager.RemoveItem(item); RefreshInteractionState(); if (_owningPuzzle != null) await _owningPuzzle.NotifyClockStateChanged(); } private void RefreshInteractionState() { bool bothPlaced = AreBothHandsPlaced(); bool canPlaceHands = !_locked && !bothPlaced; if (CanvasGroup != null) { CanvasGroup.blocksRaycasts = canPlaceHands; CanvasGroup.interactable = canPlaceHands; } _hourHand?.SetCanRotate(!_locked && bothPlaced); _minuteHand?.SetCanRotate(!_locked && bothPlaced); } private bool IsInteractable() { return !_locked && !AreBothHandsPlaced(); } } }