using System; using System.Collections.Generic; using GeometryTD.Definition; using UnityEngine; using Random = UnityEngine.Random; namespace GeometryTD.UI { public class RewardSelectFormUseCase : IUIUseCase { private readonly List _rewardPool = new List(); private RewardSelectFormRawData _currentModel; private Action _onRewardSelected; private Action _onGiveUp; private int _displayCount = 3; private int _refreshCost; private bool _allowRefreshOnce = true; private bool _allowGiveUp = true; private bool _hasRefreshed; private string _tipText = "Select one reward"; public void ConfigureRewardPool( IReadOnlyList rewardPool, int displayCount = 3, int refreshCost = 0, bool allowRefreshOnce = true, bool allowGiveUp = true, string tipText = null) { _rewardPool.Clear(); if (rewardPool != null) { foreach (var item in rewardPool) { if (item == null) { continue; } _rewardPool.Add(item); } } _displayCount = Mathf.Max(1, displayCount); _refreshCost = Mathf.Max(0, refreshCost); _allowRefreshOnce = allowRefreshOnce; _allowGiveUp = allowGiveUp; _tipText = string.IsNullOrWhiteSpace(tipText) ? "Select one reward" : tipText; _hasRefreshed = false; _currentModel = null; } public void ConfigureRewardCandidates( IReadOnlyList rewardCandidates, int displayCount = 3, int refreshCost = 0, bool allowRefreshOnce = true, bool allowGiveUp = true, string tipText = null) { _rewardPool.Clear(); if (rewardCandidates != null) { foreach (var item in rewardCandidates) { if (item == null) { continue; } _rewardPool.Add(RewardSelectItemRawDataBuilder.Build(item)); } } _displayCount = Mathf.Max(1, displayCount); _refreshCost = Mathf.Max(0, refreshCost); _allowRefreshOnce = allowRefreshOnce; _allowGiveUp = allowGiveUp; _tipText = string.IsNullOrWhiteSpace(tipText) ? "Select one reward" : tipText; _hasRefreshed = false; _currentModel = null; } public void SetCallbacks(Action onRewardSelected, Action onGiveUp = null) { _onRewardSelected = onRewardSelected; _onGiveUp = onGiveUp; } public RewardSelectFormRawData CreateInitialModel() { _hasRefreshed = false; _currentModel = BuildModel(); return _currentModel; } public RewardSelectFormRawData TryRefresh() { if (_currentModel == null) { return null; } if (!CanRefreshInternal()) { return _currentModel; } if (!TryConsumeRefreshCost()) { _currentModel.CanRefresh = false; return _currentModel; } _hasRefreshed = true; _currentModel = BuildModel(); return _currentModel; } public RewardSelectFormRawData SelectReward(int selectedIndex) { if (_currentModel?.RewardItems == null || _currentModel.RewardItems.Length <= 0) { return null; } if (selectedIndex < 0 || selectedIndex >= _currentModel.RewardItems.Length) { return _currentModel; } RewardSelectItemRawData selectedReward = _currentModel.RewardItems[selectedIndex]; _onRewardSelected?.Invoke(selectedReward); _currentModel = null; return null; } public bool TryGiveUp() { if (!_allowGiveUp) { return false; } _onGiveUp?.Invoke(); _currentModel = null; return true; } private RewardSelectFormRawData BuildModel() { RewardSelectItemRawData[] selectedRewards = SelectRewards(); return new RewardSelectFormRawData { TipText = _tipText, RewardItems = selectedRewards, RefreshCost = _refreshCost, CanRefresh = selectedRewards.Length > 0 && CanRefreshInternal(), CanGiveUp = _allowGiveUp }; } private RewardSelectItemRawData[] SelectRewards() { if (_rewardPool.Count <= 0) { return Array.Empty(); } int finalCount = Mathf.Clamp(_displayCount, 1, _rewardPool.Count); int[] indexes = new int[_rewardPool.Count]; for (int i = 0; i < indexes.Length; i++) { indexes[i] = i; } for (int i = 0; i < finalCount; i++) { int randomIndex = Random.Range(i, indexes.Length); (indexes[i], indexes[randomIndex]) = (indexes[randomIndex], indexes[i]); } RewardSelectItemRawData[] results = new RewardSelectItemRawData[finalCount]; for (int i = 0; i < finalCount; i++) { RewardSelectItemRawData source = _rewardPool[indexes[i]]; results[i] = source; } return results; } private bool CanRefreshInternal() { if (!_allowRefreshOnce || _hasRefreshed) { return false; } return CanPayRefreshCost(); } private bool CanPayRefreshCost() { if (_refreshCost <= 0) { return true; } if (GameEntry.PlayerInventory == null) { return true; } return GameEntry.PlayerInventory.Gold >= _refreshCost; } private bool TryConsumeRefreshCost() { if (_refreshCost <= 0) { return true; } if (GameEntry.PlayerInventory == null) { return true; } return GameEntry.PlayerInventory.TryConsumeGold(_refreshCost); } } }