using System;
using System.Collections.Generic;
using System.Linq;
using AibisDream.Kit;
using AibisDream.SaveSystem;
using UnityEngine;
namespace AibisDream.FixSystem
{
///
/// 打孔带系统入口:收藏数据、Yarn 命令、弹窗与收藏夹面板代理。
///
public class PunchTapeManager : Singleton
{
public GameObject punchTapecluePrefab;
[SerializeField] private PunchTapeCatalog punchTapeCatalog;
public PunchTapeCatalog Catalog => punchTapeCatalog;
[SerializeField] private PunchTapeFavoritesPanel favoritesPanel;
public PunchTapeFavoritesPanel FavoritesPanel => favoritesPanel;
[SerializeField] private PunchTapePrinter punchTapePrinter;
public PunchTapePrinter PunchTapePrinter => punchTapePrinter;
private readonly List _favorites = new();
private GameObject currentPunchTapeGO;
/// 收藏列表变更时通知 等订阅方。
public event Action OnCollectionChanged;
public IReadOnlyList GetFavorites()
{
return _favorites;
}
public PunchTapeSnapshotDto CapturePunchTapeSnapshot()
{
return new PunchTapeSnapshotDto
{
favorites = _favorites.Select(t => new PunchTape(t.DefinitionId)
{
used = t.used
}).ToList()
};
}
public void ApplyPunchTapeSnapshot(PunchTapeSnapshotDto dto)
{
_favorites.Clear();
if (dto?.favorites != null)
{
foreach (var tape in dto.favorites)
{
if (!TryGetDefinition(tape, out _))
{
Debug.LogWarning(
$"[PunchTapeManager] 存档中的打孔带 ID '{tape?.DefinitionId ?? ""}' 无法解析,已跳过。",
this);
continue;
}
if (!_favorites.Contains(tape))
_favorites.Add(tape);
}
}
OnCollectionChanged?.Invoke();
}
public void AddPunchTape(PunchTape punchTape)
{
if (punchTape == null) return;
if (!TryGetDefinition(punchTape, out _))
{
Debug.LogError($"[PunchTapeManager] 无法收藏未知打孔带 '{punchTape.DefinitionId}'。", this);
return;
}
if (_favorites.Contains(punchTape))
return;
_favorites.Add(punchTape);
OnCollectionChanged?.Invoke();
}
public void RemovePunchTape(PunchTape punchTape)
{
if (punchTape == null) return;
if (!_favorites.Remove(punchTape))
return;
OnCollectionChanged?.Invoke();
}
public void OpenFavoritesPanel()
{
if (favoritesPanel == null)
{
Debug.LogWarning("[PunchTapeManager] 未指定 _favoritesPanel,无法打开收藏夹面板。", this);
return;
}
favoritesPanel.OpenPanel();
}
public void CloseFavoritesPanel()
{
if (favoritesPanel == null)
{
Debug.LogWarning("[PunchTapeManager] 未指定 _favoritesPanel,无法关闭收藏夹面板。", this);
return;
}
favoritesPanel.ClosePanel();
}
public bool TryGetDefinition(string definitionId, out PunchTapeDefinition definition)
{
definition = null;
if (punchTapeCatalog == null)
{
Debug.LogError("[PunchTapeManager] 未配置 PunchTapeCatalog。", this);
return false;
}
var catalogErrors = punchTapeCatalog.GetValidationErrors();
if (catalogErrors.Count > 0)
{
Debug.LogError(
$"[PunchTapeManager] PunchTapeCatalog 配置无效:\n{string.Join("\n", catalogErrors)}",
this);
return false;
}
if (!punchTapeCatalog.TryGetDefinition(definitionId, out definition))
{
Debug.LogError($"[PunchTapeManager] 未找到打孔带 ID '{definitionId}'。", this);
definition = null;
return false;
}
if (!definition.TryValidate(out var error))
{
Debug.LogError($"[PunchTapeManager] 打孔带 ID '{definitionId}' 无效:{error}", this);
definition = null;
return false;
}
return true;
}
public bool TryGetDefinition(PunchTape punchTape, out PunchTapeDefinition definition)
{
return TryGetDefinition(punchTape?.DefinitionId, out definition);
}
public void GeneratePunchTapeWindow(string definitionId, bool directlyAddToFavorites = false)
{
if (!TryGetDefinition(definitionId, out var definition))
return;
PunchTape punchTape = new PunchTape(definitionId);
if (directlyAddToFavorites)
{
AddPunchTape(punchTape);
return;
}
GameObject go = Instantiate(punchTapecluePrefab, favoritesPanel.transform);
PunchTapeItem item = go.GetComponent();
if (item == null)
{
Debug.LogError("[PunchTapeManager] 生成 Prefab 缺少 PunchTapeItem。", go);
Destroy(go);
return;
}
currentPunchTapeGO = go;
item.Setup(punchTape, definition);
}
///
/// 将当前弹窗中的打孔带收入收藏。兼容旧 Yarn:<<CollectionClue ClueManager>> 会传入参数,仍应执行收藏。
///
public void CollectPunchTapeFromWindow()
{
if (currentPunchTapeGO == null)
{
Debug.LogWarning("PunchTapeManager: 没有当前打孔带窗口,无法收藏。");
return;
}
PunchTapeItem item = currentPunchTapeGO.GetComponent();
if (item == null)
{
Debug.LogWarning("PunchTapeManager: 当前物体上缺少 PunchTapeItem。");
return;
}
AddPunchTape(item.GetPunchTapeData());
Destroy(currentPunchTapeGO.gameObject);
currentPunchTapeGO = null;
}
}
}