using System; using System.Collections.Generic; using GeometryTD.Definition; using UnityEngine; 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 _allowRotateOnce = true; private bool _allowGiveUp = true; private bool _hasRotated; private int _selectionOffset; private string _tipText = "Select one reward"; // RewardSelectForm keeps a fixed reward pool for the current node. // The "refresh" action only rotates which slice of that pool is shown so save/load // can reopen the same node with the exact same reward contents. public void ConfigureRewardPool( IReadOnlyList rewardPool, int displayCount = 3, int refreshCost = 0, bool allowRotateOnce = 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); _allowRotateOnce = allowRotateOnce; _allowGiveUp = allowGiveUp; _tipText = string.IsNullOrWhiteSpace(tipText) ? "Select one reward" : tipText; _hasRotated = false; _selectionOffset = 0; _currentModel = null; } public void ConfigureRewardCandidates( IReadOnlyList rewardCandidates, int displayCount = 3, int refreshCost = 0, bool allowRotateOnce = 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); _allowRotateOnce = allowRotateOnce; _allowGiveUp = allowGiveUp; _tipText = string.IsNullOrWhiteSpace(tipText) ? "Select one reward" : tipText; _hasRotated = false; _selectionOffset = 0; _currentModel = null; } public void SetCallbacks(Action onRewardSelected, Action onGiveUp = null) { _onRewardSelected = onRewardSelected; _onGiveUp = onGiveUp; } public RewardSelectFormRawData CreateInitialModel() { _hasRotated = false; _currentModel = BuildModel(); return _currentModel; } public RewardSelectFormRawData TryRotateSelection() { if (_currentModel == null) { return null; } if (!CanRotateSelectionInternal()) { return _currentModel; } if (!TryConsumeRotateCost()) { _currentModel.CanRefresh = false; return _currentModel; } _hasRotated = true; if (_rewardPool.Count > 0) { _selectionOffset = (_selectionOffset + _displayCount) % _rewardPool.Count; } _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 && CanRotateSelectionInternal(), CanGiveUp = _allowGiveUp }; } private RewardSelectItemRawData[] SelectRewards() { if (_rewardPool.Count <= 0) { return Array.Empty(); } int finalCount = Mathf.Clamp(_displayCount, 1, _rewardPool.Count); RewardSelectItemRawData[] results = new RewardSelectItemRawData[finalCount]; for (int i = 0; i < finalCount; i++) { int sourceIndex = (_selectionOffset + i) % _rewardPool.Count; RewardSelectItemRawData source = _rewardPool[sourceIndex]; results[i] = source; } return results; } private bool CanRotateSelectionInternal() { if (!_allowRotateOnce || _hasRotated) { return false; } return CanPayRotateCost(); } private bool CanPayRotateCost() { if (_refreshCost <= 0) { return true; } if (GameEntry.PlayerInventory == null) { return true; } return GameEntry.PlayerInventory.Gold >= _refreshCost; } private bool TryConsumeRotateCost() { if (_refreshCost <= 0) { return true; } if (GameEntry.PlayerInventory == null) { return true; } return GameEntry.PlayerInventory.TryConsumeGold(_refreshCost); } } }