using System.Collections;
using UnityEngine;
using UnityEngine.UI;
namespace Streamingle.Contents.BossRaid
{
///
/// 콤보 카운터 UI. 컴팩트 디자인, 오른쪽 수직 중앙.
/// 히트 시 슬라이드 인 + 펀치 스케일, 타임아웃 시 슬라이드 아웃.
///
public class ComboCounter : MonoBehaviour
{
#region Fields
[Header("설정")]
[SerializeField] private float comboTimeout = 2f;
[Header("비주얼")]
[SerializeField] private Color comboColor = new Color(1f, 0.85f, 0.15f);
[SerializeField] private Color labelColor = new Color(0.85f, 0.85f, 0.9f);
[SerializeField] private int baseFontSize = 80;
[SerializeField] private int maxFontSize = 120;
[SerializeField] private int fontSizeGrowPerHit = 1;
private Canvas _canvas;
private CanvasGroup _canvasGroup;
private Text _comboText;
private Text _hitLabel;
private RectTransform _rootRect;
private int _currentCombo;
private float _lastHitTime;
private Coroutine _punchCoroutine;
private Coroutine _slideCoroutine;
private Font _font;
private bool _isShowing;
// 슬라이드 위치 (화면 오른쪽 밖 → 안)
private const float OffScreenX = 120f;
private const float OnScreenX = -40f;
#endregion
#region Properties
public int CurrentCombo => _currentCombo;
#endregion
#region Unity Messages
private void Awake()
{
_font = BossRaidFontLoader.Load();
CreateUI();
_canvasGroup.alpha = 0f;
_isShowing = false;
}
private void Update()
{
if (_currentCombo <= 0) return;
if (Time.time - _lastHitTime > comboTimeout)
SlideOut();
}
#endregion
#region Public Methods
public void RegisterHit()
{
_currentCombo++;
_lastHitTime = Time.time;
UpdateDisplay();
// 슬라이드 인 (처음이거나 숨겨진 상태일 때)
if (!_isShowing)
SlideIn();
// 펀치 스케일
if (_punchCoroutine != null) StopCoroutine(_punchCoroutine);
_punchCoroutine = StartCoroutine(PunchCoroutine());
}
public void ResetCombo()
{
_currentCombo = 0;
_isShowing = false;
if (_canvasGroup != null) _canvasGroup.alpha = 0f;
}
public void Hide()
{
ResetCombo();
}
#endregion
#region Private Methods
private void UpdateDisplay()
{
_comboText.text = _currentCombo.ToString();
_comboText.fontSize = Mathf.Min(baseFontSize + _currentCombo * fontSizeGrowPerHit, maxFontSize);
}
private void SlideIn()
{
if (_slideCoroutine != null) StopCoroutine(_slideCoroutine);
_slideCoroutine = StartCoroutine(SlideCoroutine(OffScreenX, OnScreenX, 0f, 1f, 0.2f));
_isShowing = true;
}
private void SlideOut()
{
if (!_isShowing) return;
if (_slideCoroutine != null) StopCoroutine(_slideCoroutine);
_slideCoroutine = StartCoroutine(SlideOutAndReset());
}
private IEnumerator SlideCoroutine(float fromX, float toX, float fromAlpha, float toAlpha, float duration)
{
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
float ease = 1f - (1f - t) * (1f - t); // EaseOutQuad
_rootRect.anchoredPosition = new Vector2(Mathf.Lerp(fromX, toX, ease), _rootRect.anchoredPosition.y);
_canvasGroup.alpha = Mathf.Lerp(fromAlpha, toAlpha, ease);
yield return null;
}
_rootRect.anchoredPosition = new Vector2(toX, _rootRect.anchoredPosition.y);
_canvasGroup.alpha = toAlpha;
_slideCoroutine = null;
}
private IEnumerator SlideOutAndReset()
{
yield return SlideCoroutine(OnScreenX, OffScreenX, 1f, 0f, 0.3f);
_currentCombo = 0;
_isShowing = false;
}
private IEnumerator PunchCoroutine()
{
var rect = _comboText.rectTransform;
float punchSize = 1.4f;
float duration = 0.12f;
float elapsed = 0f;
rect.localScale = Vector3.one * punchSize;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float t = elapsed / duration;
// EaseOutBack
float ease = 1f + 2.7f * Mathf.Pow(t - 1f, 3f) + 1.7f * Mathf.Pow(t - 1f, 2f);
rect.localScale = Vector3.one * Mathf.LerpUnclamped(punchSize, 1f, ease);
yield return null;
}
rect.localScale = Vector3.one;
_punchCoroutine = null;
}
private void CreateUI()
{
var canvasObj = new GameObject("BossRaid_ComboCounter");
canvasObj.transform.SetParent(transform);
_canvas = canvasObj.AddComponent