using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using BaseGames.Core;
using BaseGames.Core.Events;
using BaseGames.Skills;
using BaseGames.Localization;
namespace BaseGames.UI
{
///
/// 形态技能一览面板(架构 10_UIModule §Panel)。
/// 只读面板:按形态展示各技能槽的技能资料(名称、描述、消耗、冷却),不含任何解锁/技能点交互。
/// 支持左右翻页浏览各形态,并高亮当前实际使用的形态。
///
/// Inspector 必填:
/// _formSkillSets — 每个形态对应一条配置(soulSkill + spirit1 + spirit2)
/// _formTitleText — 显示当前形态标签名的文本
/// _prevFormBtn / _nextFormBtn — 翻页按钮
/// _activeFormIndicator — 高亮"当前形态"的标志(可选,如小圆点)
/// _skillSlots — 3 个 SkillSlotView 引用(Soul / Spirit1 / Spirit2)
/// _onFormChanged — IntEventChannelSO,FormController 广播当前形态 index
///
public class FormSkillPanel : MonoBehaviour
{
// ── 子数据结构 ────────────────────────────────────────────────────────
[System.Serializable]
public struct FormSkillConfig
{
[Tooltip("形态标题的本地化 Key,格式如 \"Form_SkyWarden_Label\",由 LocalizationManager.Get(…, LocalizationTable.UI) 查找。")]
public string formLabelKey;
[Tooltip("天魂/地魂/命魂的「魂技」")]
public FormSkillSO soulSkill;
[Tooltip("灵技 1(Y / Triangle / 手柄按钮)")]
public FormSkillSO spiritSkill1;
[Tooltip("灵技 2(Shift+Y / L2+Triangle 等)")]
public FormSkillSO spiritSkill2;
}
[System.Serializable]
public struct SkillSlotView
{
[Tooltip("技能图标")]
public Image icon;
[Tooltip("技能名称文本")]
public TMP_Text nameText;
[Tooltip("技能描述文本")]
public TMP_Text descText;
[Tooltip("消耗数值文本(如 \"魂力 25\")")]
public TMP_Text costText;
[Tooltip("冷却数值文本(如 \"CD 3.5s\")")]
public TMP_Text cooldownText;
[Tooltip("无技能时隐藏的根 GameObject")]
public GameObject root;
}
// ── Inspector 字段 ────────────────────────────────────────────────────
[Header("形态技能配置")]
[Tooltip("每个元素对应一种形态的三项技能,顺序应与 FormType 枚举序号一致。")]
[SerializeField] private FormSkillConfig[] _formSkillSets;
[Header("UI 导航")]
[SerializeField] private TMP_Text _formTitleText;
[SerializeField] private Button _prevFormBtn;
[SerializeField] private Button _nextFormBtn;
[Tooltip("高亮当前实际装备形态的指示器(可选)")]
[SerializeField] private GameObject _activeFormIndicator;
[Header("技能卡槽(Soul / Spirit1 / Spirit2)")]
[SerializeField] private SkillSlotView _soulSlot;
[SerializeField] private SkillSlotView _spiritSlot1;
[SerializeField] private SkillSlotView _spiritSlot2;
[Header("关闭按钮")]
[SerializeField] private Button _btnClose;
[Header("Event Channels")]
[Tooltip("FormController 广播当前形态切换:payload = FormType 的整数序号(0=天魂,1=地魂,2=命魂)")]
[SerializeField] private IntEventChannelSO _onFormChanged;
// ── 私有状态 ──────────────────────────────────────────────────────────
private int _viewIndex = 0; // 当前正在查看的形态
private int _activeIndex = 0; // 玩家当前实际使用的形态
private readonly CompositeDisposable _subs = new();
// ── 生命周期 ──────────────────────────────────────────────────────────
private void Awake()
{
_prevFormBtn?.onClick.AddListener(PrevForm);
_nextFormBtn?.onClick.AddListener(NextForm);
_btnClose?.onClick.AddListener(OnCloseClicked);
}
private void OnEnable()
{
_onFormChanged?.Subscribe(OnFormChanged).AddTo(_subs);
// 打开时自动跳到当前形态
_viewIndex = _activeIndex;
Refresh();
}
private void OnDisable()
{
_subs.Clear();
}
// ── 事件处理 ──────────────────────────────────────────────────────────
private void OnFormChanged(int formIndex)
{
_activeIndex = formIndex;
if (_activeFormIndicator != null)
_activeFormIndicator.SetActive(_viewIndex == _activeIndex);
}
// ── 导航 ──────────────────────────────────────────────────────────────
private void PrevForm()
{
if (_formSkillSets == null || _formSkillSets.Length == 0) return;
_viewIndex = (_viewIndex - 1 + _formSkillSets.Length) % _formSkillSets.Length;
Refresh();
}
private void NextForm()
{
if (_formSkillSets == null || _formSkillSets.Length == 0) return;
_viewIndex = (_viewIndex + 1) % _formSkillSets.Length;
Refresh();
}
// ── 显示刷新 ──────────────────────────────────────────────────────────
private void Refresh()
{
if (_formSkillSets == null || _formSkillSets.Length == 0) return;
_viewIndex = Mathf.Clamp(_viewIndex, 0, _formSkillSets.Length - 1);
var cfg = _formSkillSets[_viewIndex];
// 标题(走本地化管道,fallback 为 key 本身)
if (_formTitleText != null)
{
string label = !string.IsNullOrEmpty(cfg.formLabelKey)
? LocalizationManager.Get(cfg.formLabelKey, LocalizationTable.UI)
: string.Empty;
_formTitleText.text = string.IsNullOrEmpty(label) || label == cfg.formLabelKey
? cfg.formLabelKey // fallback:直接显示 Key
: label;
}
// 当前形态高亮指示器
if (_activeFormIndicator != null)
_activeFormIndicator.SetActive(_viewIndex == _activeIndex);
// 翻页按钮可见性(只有一种形态时隐藏)
bool multiForm = _formSkillSets.Length > 1;
if (_prevFormBtn != null) _prevFormBtn.gameObject.SetActive(multiForm);
if (_nextFormBtn != null) _nextFormBtn.gameObject.SetActive(multiForm);
// 技能卡槽
FillSlot(ref _soulSlot, cfg.soulSkill);
FillSlot(ref _spiritSlot1, cfg.spiritSkill1);
FillSlot(ref _spiritSlot2, cfg.spiritSkill2);
}
private static void FillSlot(ref SkillSlotView slot, FormSkillSO skill)
{
bool hasSkill = skill != null;
if (slot.root != null) slot.root.SetActive(hasSkill);
if (!hasSkill) return;
if (slot.icon != null)
{
slot.icon.sprite = skill.icon;
slot.icon.enabled = skill.icon != null;
}
if (slot.nameText != null)
{
string name = LocalizationManager.Get(skill.displayNameKey, LocalizationTable.UI);
slot.nameText.text = string.IsNullOrEmpty(name) || name == skill.displayNameKey
? skill.skillId
: name;
}
if (slot.descText != null)
{
string desc = LocalizationManager.Get(skill.descriptionKey, LocalizationTable.UI);
slot.descText.text = string.IsNullOrEmpty(desc) || desc == skill.descriptionKey
? string.Empty
: desc;
}
if (slot.costText != null)
slot.costText.text = skill.baseCost > 0
? $"{skill.resourceType} {skill.baseCost}"
: string.Empty;
if (slot.cooldownText != null)
slot.cooldownText.text = skill.cooldown > 0f
? $"CD {skill.cooldown:0.#}s"
: string.Empty;
}
// ── 关闭 ──────────────────────────────────────────────────────────────
private void OnCloseClicked()
{
var uiMgr = ServiceLocator.GetOrDefault();
if (uiMgr != null) uiMgr.CloseTopPanel();
else gameObject.SetActive(false);
}
}
}