using System; using System.Collections.Generic; using System.Linq; using UnityEngine; public class VitrinaPanel : MonoBehaviour, IControlable { public event Action OnComplete; [SerializeField] private Transform BoxesRoot; [SerializeField] private GameObject BoxViewPrefab; private readonly List _generatedBoxes = new(); private int _pointerIndex; private bool _initialized; private bool _waitForActionRelease; private bool _waitingForResult; public bool ControlsEnabled { get; set; } private VitrinaBox CurrentBox => _generatedBoxes[_pointerIndex]; private void OnDisable() { ControlsEnabled = false; _initialized = false; _waitingForResult = false; UnsubscribeFromResult(); ClearBoxes(); } public async void Initialize(int[] requiredBoxes) { if (_initialized) return; _initialized = true; ControlsEnabled = false; ClearBoxes(); if (VitrinaCatcher.Instance == null) { Debug.LogError("VitrinaCatcher не инициализирован", gameObject); _initialized = false; gameObject.SetActive(false); OnComplete?.Invoke(false); return; } SubscribeToResult(); if (!PrizeStandController.Initialized) { _waitingForResult = true; VitrinaCatcher.Instance.DisplayOpenResult(false, "Витрина не подключена"); return; } int[] readyBoxes = await PrizeStandController.GetReadyBoxesAsync(); if (!_initialized) return; int[] availableBoxes = FindIntersection(requiredBoxes, readyBoxes); if (availableBoxes.Length == 0) { _waitingForResult = true; VitrinaCatcher.Instance.DisplayOpenResult(false, "Нет доступных призов в витрине"); return; } _pointerIndex = 0; GenerateBoxes(availableBoxes); CurrentBox.SetEnabled(true); _waitForActionRelease = true; ControlsEnabled = true; ControlsPerformer.Instance.SetControlable(this); } public void UpdateControls() { if (!_initialized || _waitingForResult) return; if (_waitForActionRelease) { if (In.GetAction(JoystickSide.Both, InteractMode.Continious)) return; _waitForActionRelease = false; } int direction = In.GetAxis(JoystickSide.Both, InteractMode.Discrete).x; if (direction != 0 && _generatedBoxes.Count > 1) { CurrentBox.SetEnabled(false); CurrentBox.shake = false; _pointerIndex = (_pointerIndex + direction + _generatedBoxes.Count) % _generatedBoxes.Count; CurrentBox.SetEnabled(true); } if (!In.GetAction(JoystickSide.Both, InteractMode.Discrete)) return; ControlsEnabled = false; ControlsPerformer.Instance.SetControlable(null); CurrentBox.shake = true; _waitingForResult = true; _ = PrizeStandController.OpenBoxAsync(CurrentBox.Number); } public static int[] FindIntersection(int[] array1, int[] array2) { if (array1 == null || array2 == null || array1.Length == 0 || array2.Length == 0) return Array.Empty(); HashSet requiredBoxes = new(array1); return array2.Where(requiredBoxes.Contains).Distinct().OrderBy(number => number).ToArray(); } public void Close() { ControlsEnabled = false; ControlsPerformer.Instance.SetControlable(null); gameObject.SetActive(false); } private void GenerateBoxes(int[] indexes) { foreach (int index in indexes) { GameObject boxObject = Instantiate(BoxViewPrefab, BoxesRoot); if (boxObject.TryGetComponent(out VitrinaBox box)) { _generatedBoxes.Add(box); box.SetNumber(index); } else { Destroy(boxObject); Debug.LogError("Префаб не содержит компонента VitrinaBox", gameObject); } } } private void ClearBoxes() { foreach (VitrinaBox box in _generatedBoxes) { if (box != null) Destroy(box.gameObject); } _generatedBoxes.Clear(); } private void SubscribeToResult() { if (VitrinaCatcher.Instance == null) return; VitrinaCatcher.Instance.ResultClosed -= HandleResultClosed; VitrinaCatcher.Instance.ResultClosed += HandleResultClosed; } private void UnsubscribeFromResult() { if (VitrinaCatcher.Instance != null) VitrinaCatcher.Instance.ResultClosed -= HandleResultClosed; } private void HandleResultClosed(bool success) { if (!_initialized || !_waitingForResult) return; UnsubscribeFromResult(); _initialized = false; _waitingForResult = false; gameObject.SetActive(false); OnComplete?.Invoke(success); } }