using System;
using System.Collections.Generic;
using UnityEngine;
using RR.Common.Prizes;
using RR.Common.Settings;
using RR.Common.UI;
using RR.Common.Utility;
using RR.Game2D.Core.Managers;
namespace RR.Common.Managers
{
///
/// Центральный менеджер системы призов.
/// Не знает конкретики о призах — читает конфигурацию из JSON ()
/// и делегирует выдачу зарегистрированным исполнителям ().
///
public class PrizeSystemManager : MonoBehaviour
{
public static PrizeSystemManager Instance { get; private set; }
[Header("QR-коды (глобальная конфигурация)")]
[SerializeField] private List qrCodes = new();
[SerializeField] private string phoneNumberMask = "+7XXXXXXXXXX";
/// Хранилище призов за уровни (JSON).
public PrizeDatabase Database { get; private set; }
///
/// Вызывается после выдачи любого приза. Параметры: тип приза, успех.
///
public event Action OnAnyPrizeResult;
// ── Исполнители ──
private readonly Dictionary _executors = new();
// ── QR-коды ──
private readonly List _generatedQRCodes = new();
private Texture2D[] _qrCodesCache;
private bool _qrCodesDirty = true;
private string _phoneNumber = string.Empty;
// ────────────── Инициализация ──────────────
public void Initialize()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
// Загружаем базу призов из JSON
Database = new PrizeDatabase();
Database.Load();
// QR-коды (глобальные)
RefreshPhoneNumber();
GenerateQRCodes();
SubscribeToSettings();
// Регистрируем исполнителей — модальные окна регистрируют себя сами через static Current
RegisterExecutor(new NonePrize());
RegisterExecutor(new QRCodePrize(() => QRCodeModal.Current, GetQRCodes));
RegisterExecutor(new HopperPrize());
RegisterExecutor(new PrizeStandPrize(() => PrizeStandModal.Current));
Debug.Log("[PrizeSystemManager] Инициализирован. " +
$"Исполнители: {_executors.Count}, Уровней в базе: {Database.GetAll().Count}");
}
private void OnDestroy()
{
UnsubscribeFromSettings();
if (Instance == this) Instance = null;
}
// ────────────── Публичный API ──────────────
///
/// Выдаёт приз за текущий уровень (World-Stage).
/// Конфигурация берётся из .
///
public void GivePrizeForCurrentLevel()
{
string level = $"{GameManager.Instance.World}-{GameManager.Instance.Stage}";
GivePrizeForLevel(level);
}
///
/// Выдаёт приз за указанный уровень.
///
public void GivePrizeForLevel(string levelName)
{
LevelPrizeConfig config = Database.GetConfig(levelName);
if (config.type == PrizeType.None)
{
Debug.Log($"[PrizeSystemManager] Уровень «{levelName}»: приз не назначен.");
OnAnyPrizeResult?.Invoke(PrizeType.None, true);
return;
}
if (!_executors.TryGetValue(config.type, out PrizeBase executor))
{
Debug.LogWarning($"[PrizeSystemManager] Нет исполнителя для типа «{config.type}».");
return;
}
if (executor.IsGiving)
{
Debug.LogWarning($"[PrizeSystemManager] Исполнитель «{config.type}» занят.");
return;
}
Debug.Log($"[PrizeSystemManager] Уровень «{levelName}» → приз «{config.type}».");
executor.Execute(this, config);
}
///
/// Обратная совместимость: выдаёт приз хоппером (если включён в настройках).
///
public void GivePrize()
{
bool hopperEnabled = SettingsManager.Instance != null
&& SettingsManager.Instance.GetBool("prizes.giveSmallPrize");
if (hopperEnabled && _executors.TryGetValue(PrizeType.Hopper, out PrizeBase executor))
executor.Execute(this, new LevelPrizeConfig { type = PrizeType.Hopper });
else
Debug.Log("[PrizeSystemManager] Хоппер отключён в настройках.");
}
///
/// Выдаёт приз указанного типа с конфигурацией по умолчанию.
///
public void GivePrize(PrizeType type)
{
if (!_executors.TryGetValue(type, out PrizeBase executor))
{
Debug.LogWarning($"[PrizeSystemManager] Нет исполнителя для «{type}».");
return;
}
executor.Execute(this, new LevelPrizeConfig { type = type });
}
/// Возвращает QR-коды (кешируется до перегенерации).
public Texture2D[] GetQRCodes()
{
if (_qrCodesDirty || _qrCodesCache == null)
{
_qrCodesCache = _generatedQRCodes.ToArray();
_qrCodesDirty = false;
}
return _qrCodesCache;
}
/// Идёт ли выдача какого-либо приза.
public bool IsAnyPrizeGiving
{
get
{
foreach (PrizeBase ex in _executors.Values)
if (ex.IsGiving) return true;
return false;
}
}
// ────────────── Регистрация исполнителей ──────────────
/// Регистрирует исполнитель приза. Заменяет предыдущий для того же типа.
public void RegisterExecutor(PrizeBase executor)
{
_executors[executor.Type] = executor;
executor.OnPrizeResult += success => OnAnyPrizeResult?.Invoke(executor.Type, success);
}
// ────────────── QR-коды (глобальная генерация) ──────────────
private void RefreshPhoneNumber()
{
var settings = SettingsManager.Instance;
_phoneNumber = settings?.GetString("prizes.phoneNumber") ?? string.Empty;
_phoneNumber = PhoneNumberUtils.ValidatePhoneNumber(_phoneNumber);
_phoneNumber = PhoneNumberUtils.ApplyPhoneMask(_phoneNumber, phoneNumberMask);
}
private void GenerateQRCodes()
{
_generatedQRCodes.Clear();
_qrCodesDirty = true;
foreach (QRCodeInfo data in qrCodes)
{
if (!data.generateQRCode) continue;
string fullLink = data.GetFullLink(_phoneNumber);
Texture2D tex = QRMaker.MakeTexture(
fullLink, 8, true,
QRCodeInfo.GetColor(data.darkColor),
QRCodeInfo.GetColor(data.lightColor));
_generatedQRCodes.Add(tex);
}
}
// ────────────── Настройки ──────────────
private void SubscribeToSettings()
{
var settings = SettingsManager.Instance;
if (settings != null) settings.OnSettingChanged += OnSettingChanged;
}
private void UnsubscribeFromSettings()
{
var settings = SettingsManager.Instance;
if (settings != null) settings.OnSettingChanged -= OnSettingChanged;
}
private void OnSettingChanged(string key, SettingValue value)
{
if (key == "prizes.phoneNumber")
{
RefreshPhoneNumber();
GenerateQRCodes();
Debug.Log("[PrizeSystemManager] QR-коды перегенерированы.");
}
}
}
}