using System;
using System.Collections.Generic;
using UnityEngine;
using RR.Common.Controls;
using RR.Common.Managers;
using RR.Common.UI;
using RR.Game2D.Behaviour;
using RR.Game2D.Core.Managers;
using ControlsBoxStatus = RR.Common.Controls.BoxStatus;
namespace RR.Common.Prizes
{
///
/// Исполнитель приза «Витрина».
/// Показывает модальное окно с выбором ячейки, затем открывает её
/// через . Количество ячеек берётся из ComSystemManager.
///
public class PrizeStandPrize : PrizeBase
{
public override PrizeType Type => PrizeType.PrizeStand;
public override bool IsGiving => _isGiving;
private readonly Func _resolveModal;
private bool _isGiving;
private PrizeStandModal _activeModal;
/// Делегат для поиска модального окна в текущих сценах.
public PrizeStandPrize(Func resolveModal)
{
_resolveModal = resolveModal;
}
public override void Execute(MonoBehaviour host, LevelPrizeConfig config)
{
if (_isGiving)
{
Debug.LogWarning("[PrizeStandPrize] Уже идёт выдача.");
return;
}
_isGiving = true;
ShowPrizeStandSelectionAsync();
}
private async void ShowPrizeStandSelectionAsync()
{
try
{
// Отписываемся от предыдущего модального окна, если было
if (_activeModal != null)
_activeModal.OnBoxSelected -= OnBoxSelected;
_activeModal = _resolveModal?.Invoke();
if (_activeModal == null)
{
Debug.LogError("[PrizeStandPrize] PrizeStandModal не найден на сцене.");
_isGiving = false;
InvokeResult(false);
return;
}
_activeModal.OnBoxSelected += OnBoxSelected;
PrizeStandController stand = ComSystemManager.GetPrizeStandController();
PrizeStandConnectionInfo connectionInfo = PrizeSystemManager.Instance != null
? PrizeSystemManager.Instance.GetPrizeStandConnectionInfo()
: new PrizeStandConnectionInfo(stand != null, stand != null ? stand.GetBoxesCount() : 0);
float gameTime = GameManager.Instance != null ? GameManager.Instance.GetPendingOrCurrentWinGameTime() : 0f;
int finalScore = ScoreSystem.Instance != null
? ScoreSystem.Instance.GetDisplayScore(gameTime, true)
: 0;
PrizeStandSettings settings = PrizeSystemManager.Instance != null
? PrizeSystemManager.Instance.GetPrizeStandSettings()
: new PrizeStandSettings();
Dictionary boxStatuses = new();
if (stand != null && connectionInfo.IsConnected)
{
boxStatuses = await stand.GetStatusesAsync();
}
_activeModal.Show(
BuildAvailability(settings, connectionInfo, finalScore, boxStatuses),
connectionInfo.IsConnected,
connectionInfo.ConnectedBoxesCount,
gameTime,
finalScore,
true);
}
catch (Exception ex)
{
Debug.LogError($"[PrizeStandPrize] Не удалось подготовить витрину: {ex.Message}");
if (_activeModal != null)
{
_activeModal.OnBoxSelected -= OnBoxSelected;
_activeModal = null;
}
_isGiving = false;
InvokeResult(false);
}
}
private async void OnBoxSelected(int boxNumber)
{
// Отписываемся сразу после выбора
if (_activeModal != null)
{
_activeModal.OnBoxSelected -= OnBoxSelected;
_activeModal = null;
}
if (boxNumber <= 0)
{
_isGiving = false;
InvokeResult(false);
return;
}
PrizeStandController stand = ComSystemManager.GetPrizeStandController();
if (stand == null)
{
Debug.LogError("[PrizeStandPrize] Витрина не подключена.");
_isGiving = false;
InvokeResult(false);
return;
}
bool success = false;
void OnResult(bool s, string m)
{
stand.OpeningFinished -= OnResult;
success = s;
if (!s) Debug.LogWarning($"[PrizeStandPrize] Ошибка: {m}");
}
stand.OpeningFinished += OnResult;
try
{
await stand.OpenBoxAsync(boxNumber);
}
catch (Exception ex)
{
Debug.LogError($"[PrizeStandPrize] Исключение: {ex.Message}");
stand.OpeningFinished -= OnResult;
}
_isGiving = false;
InvokeResult(success);
}
private static IReadOnlyList BuildAvailability(
PrizeStandSettings settings,
PrizeStandConnectionInfo connectionInfo,
int finalScore,
IReadOnlyDictionary boxStatuses)
{
List result = new();
if (settings?.boxes == null)
return result;
foreach (PrizeStandBoxConfig box in settings.boxes)
{
if (box == null || box.boxNumber <= 0)
continue;
bool isConnectedBox = connectionInfo.IsConnected
&& (connectionInfo.ConnectedBoxesCount <= 0 || box.boxNumber <= connectionInfo.ConnectedBoxesCount);
bool isUnlocked = finalScore >= box.requiredScore;
ControlsBoxStatus status = ControlsBoxStatus.NotFound;
if (boxStatuses != null && boxStatuses.TryGetValue(box.boxNumber, out ControlsBoxStatus foundStatus))
{
status = foundStatus;
}
result.Add(new PrizeStandBoxAvailability(
box.boxNumber,
box.requiredScore,
isUnlocked,
isConnectedBox,
status));
}
return result;
}
}
}