using System;
using System.Collections.Generic;
using asap.core;
using UnityEngine;
namespace Activity
{
///
/// 入账/扣账成功后由 发布,
/// 供各活动自行判断是否刷新入口合并红点等(避免订阅者与具体玩法耦合)。
///
public readonly struct ActivityEventTokenBalanceChanged
{
public int EventId { get; }
public ActivityEventTokenBalanceChanged(int eventId)
{
EventId = eventId;
}
}
}
namespace Activity.Services
{
///
/// 活动代币服务实现
/// 负责管理所有活动的代币数据,提供统一的存储接口
///
public class EventTokenService : IEventTokenService
{
#region 常量与字段
private const string TransitionDataKey = "TransitionData";
private readonly Dictionary _tokenData = new Dictionary();
private readonly object _lock = new object();
private bool _isInitialized = false;
#endregion
#region 初始化
///
/// 初始化服务,从 PlayFab 加载代币数据
///
public void Initialize()
{
if (_isInitialized) return;
lock (_lock)
{
if (_isInitialized) return;
try
{
// 从 PlayFab 加载数据
LoadFromPlayFab();
_isInitialized = true;
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Initialized successfully. Token count: {_tokenData.Count}");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] Initialization failed: {e.Message}\n{e.StackTrace}");
}
}
}
///
/// 从 PlayFab 加载代币数据
///
private void LoadFromPlayFab()
{
try
{
var dataStr = PlayFabMgr.Instance?.GetLocalData(TransitionDataKey);
if (!string.IsNullOrEmpty(dataStr))
{
_tokenData.Clear();
var data = Newtonsoft.Json.JsonConvert.DeserializeObject>(dataStr);
if (data != null)
{
foreach (var kvp in data)
{
_tokenData[kvp.Key] = kvp.Value;
}
}
}
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Loaded {_tokenData.Count} token entries from PlayFab");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] Failed to load from PlayFab: {e.Message}");
}
}
///
/// 保存数据到 PlayFab
///
private void SaveToPlayFab()
{
try
{
var json = Newtonsoft.Json.JsonConvert.SerializeObject(_tokenData);
PlayFabMgr.Instance?.UpdateUserDataValue(TransitionDataKey, json);
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Saved {_tokenData.Count} token entries to PlayFab");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] Failed to save to PlayFab: {e.Message}");
throw;
}
}
#endregion
#region 基础操作
public void AddToken(int eventId, int count)
{
if (eventId <= 0)
{
Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}");
return;
}
if (count == 0)
return;
lock (_lock)
{
try
{
EnsureInitialized();
var currentCount = GetTokenCount(eventId);
_tokenData[eventId] = currentCount + count;
SaveToPlayFab();
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Added {count} tokens to event {eventId}, new total: {_tokenData[eventId]}");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] AddToken failed for event {eventId}: {e.Message}");
throw;
}
}
PublishActivityEventTokenBalanceChanged(eventId);
}
public int RemoveToken(int eventId, int count)
{
if (eventId <= 0)
{
Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}");
return 0;
}
int actualRemoved = 0;
lock (_lock)
{
try
{
EnsureInitialized();
var currentCount = GetTokenCount(eventId);
actualRemoved = Mathf.Min(count, currentCount);
var newCount = currentCount - actualRemoved;
if (newCount <= 0)
{
_tokenData.Remove(eventId);
}
else
{
_tokenData[eventId] = newCount;
}
SaveToPlayFab();
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Removed {actualRemoved} tokens from event {eventId}, remaining: {newCount}");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] RemoveToken failed for event {eventId}: {e.Message}");
throw;
}
}
PublishActivityEventTokenBalanceChanged(eventId);
return actualRemoved;
}
public int GetTokenCount(int eventId)
{
if (eventId <= 0) return 0;
lock (_lock)
{
try
{
EnsureInitialized();
return _tokenData.GetValueOrDefault(eventId, 0);
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] GetTokenCount failed for event {eventId}: {e.Message}");
return 0;
}
}
}
public void SetToken(int eventId, int count)
{
if (eventId <= 0)
{
Debug.LogWarning($"[EventTokenService] Invalid eventId: {eventId}");
return;
}
lock (_lock)
{
try
{
EnsureInitialized();
_tokenData[eventId] = count;
SaveToPlayFab();
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Set event {eventId} token count to {count}");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] SetToken failed for event {eventId}: {e.Message}");
throw;
}
}
}
public void ClearToken(int eventId)
{
if (eventId <= 0) return;
lock (_lock)
{
try
{
EnsureInitialized();
if (_tokenData.Remove(eventId))
{
SaveToPlayFab();
}
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] ClearToken failed for event {eventId}: {e.Message}");
throw;
}
}
}
#endregion
#region 批量操作
public Dictionary GetAllTokens()
{
lock (_lock)
{
EnsureInitialized();
return new Dictionary(_tokenData);
}
}
public void SetTokens(Dictionary tokens)
{
if (tokens == null) return;
lock (_lock)
{
try
{
EnsureInitialized();
_tokenData.Clear();
foreach (var kvp in tokens)
{
if (kvp.Key > 0)
{
_tokenData[kvp.Key] = kvp.Value;
}
}
SaveToPlayFab();
#if UNITY_EDITOR
Debug.Log($"[EventTokenService] Set {tokens.Count} token entries");
#endif
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] SetTokens failed: {e.Message}");
throw;
}
}
}
public void ClearTokens(IEnumerable eventIds)
{
if (eventIds == null) return;
lock (_lock)
{
try
{
EnsureInitialized();
bool changed = false;
foreach (var eventId in eventIds)
{
if (_tokenData.Remove(eventId))
{
changed = true;
}
}
if (changed)
{
SaveToPlayFab();
}
}
catch (Exception e)
{
Debug.LogError($"[EventTokenService] ClearTokens failed: {e.Message}");
throw;
}
}
}
#endregion
#region 私有辅助方法
private void EnsureInitialized()
{
if (!_isInitialized)
{
Initialize();
}
}
private static void PublishActivityEventTokenBalanceChanged(int eventId)
{
try
{
GContext.Publish(new Activity.ActivityEventTokenBalanceChanged(eventId));
}
catch
{
// GContext 未就绪等
}
}
#endregion
}
}