using System;
using System.Collections;
using System.Threading;
using RR.Common.Managers;
using RR.Game2D.Core.Managers;
using UnityEngine;
namespace RR.Common.Controls
{
///
/// Система управления выдачей призов и ведения статистики игры.
/// Отвечает за процесс выдачи призов, подсчет запусков и наград.
///
public class PrizeSystem : MonoBehaviour
{
private static PrizeSystem Instance { get; set; }
private static Coroutine prizeCoroutine;
private static bool _prizing;
private static bool _lastPrizeSuccess = true;
///
/// Потокобезопасный буфер для сигнала от датчика хоппера.
/// Записывается из любого потока (ComDeviceClient, COMInput), читается из корутины Prize().
///
private static int _prizeGivenBuffer;
///
/// Устанавливает флаг выдачи приза. Потокобезопасно — можно вызывать из любого потока.
///
public static void SignalPrizeGiven()
{
Interlocked.Exchange(ref _prizeGivenBuffer, 1);
}
private static void ResetPrizeBuffer()
{
Interlocked.Exchange(ref _prizeGivenBuffer, 0);
}
private static bool IsPrizeBufferSet()
{
return Interlocked.CompareExchange(ref _prizeGivenBuffer, 0, 0) == 1;
}
public static readonly string key_starts = "STARTS";
public static readonly string key_startsNul = "STARTSNUL";
public static readonly string key_prizesgiven = "PRIZESGIVEN";
public static readonly string key_prizesgivenNul = "PRIZESGIVENNUL";
[SerializeField] AudioClip prizeErrorSound;
///
/// Вызывается после завершения выдачи приза. true — успех, false — ошибка.
///
public static event Action OnPrizeResult;
//===========================start: PUBLIC API===========================//
///
/// Возвращает true, если последняя выдача приза прошла успешно, false - если была ошибка.
///
public static bool WasLastPrizeSuccessful => _lastPrizeSuccess;
///
/// Возвращает true, если в данный момент идет процесс выдачи приза.
///
public static bool IsPrizing => _prizing;
///
/// Инициализирует систему призов и счетчики статистики.
/// Должен быть вызван один раз при запуске приложения.
///
///
/// Выполняет:
/// - Установку статического экземпляра (singleton)
/// - Инициализацию счетчиков в PlayerPrefs если они отсутствуют
/// - Подготовку системы к работе
///
public void Initialize()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
InitCounters();
}
///
/// Запускает процесс выдачи физического приза игроку.
/// Проверяет настройки и текущее состояние перед началом выдачи.
///
///
/// Условия для выдачи приза:
/// - В настройках включена выдача призов при игре с ботом
/// - В данный момент не выполняется другая выдача приза
///
/// Процесс выдачи:
/// - Включает мотор хопера
/// - Ожидает подтверждения выдачи от датчиков (10 сек таймаут)
/// - Выключает мотор по завершению
/// - Обновляет счетчики выданных призов
/// - Воспроизводит звук ошибки при неудаче
///
public static void GivePrize()
{
// bool settingEnabled = SettingsManager.instance.GetSettingValue("Выдача призов при игре с ботом") == "Выдавать";
//
// if (!settingEnabled) { DebugWindow.Message("Выдача приза отключена в настройках"); return; }
if (_prizing)
{
GameManager.Logger.Log("PrizeSystem", "Уже идет выдача приза. Не спамь кнопку.");
return;
}
//
// DebugWindow.Message("Выдаю приз");
if (prizeCoroutine != null) Instance.StopCoroutine(prizeCoroutine);
prizeCoroutine = Instance.StartCoroutine(Instance.Prize());
}
//===========================end: PUBLIC API===========================//
#region Приватные методы
private IEnumerator Prize()
{
_prizing = true;
// DebugWindow.Message("Начинаю выдачу");
const float timeout = 10; //сек
ComSystemManager.Send("301");//включаем мотор
float startTime = Time.time;
bool success = false;
ResetPrizeBuffer();
while (Time.time - startTime < timeout)
{
if (IsPrizeBufferSet())
{
success = true;
IncreasePrizeCounters();
break;
}
yield return null;
}
//Выключаем мотор
ComSystemManager.Send("300");
// DebugWindow.Message("Закончил. Успех: " + success);
_lastPrizeSuccess = success;
_prizing = false;
if (!success) AudioManager.Instance.PlaySfx(prizeErrorSound);
OnPrizeResult?.Invoke(success);
}
private static void IncreasePrizeCounters()
{
PlayerPrefs.SetInt(key_prizesgiven, PlayerPrefs.GetInt(key_prizesgiven) + 1);
PlayerPrefs.SetInt(key_prizesgivenNul, PlayerPrefs.GetInt(key_prizesgivenNul) + 1);
}
private static void InitCounters()
{
if (!PlayerPrefs.HasKey(key_starts)) PlayerPrefs.SetInt(key_starts, 0);
if (!PlayerPrefs.HasKey(key_startsNul)) PlayerPrefs.SetInt(key_startsNul, 0);
if (!PlayerPrefs.HasKey(key_prizesgiven)) PlayerPrefs.SetInt(key_prizesgiven, 0);
if (!PlayerPrefs.HasKey(key_prizesgivenNul)) PlayerPrefs.SetInt(key_prizesgivenNul, 0);
}
#endregion
}
}