using System;
using UnityEngine;

namespace IndianOceanAssets.Engine2_5D
{
    /// <summary>
    /// 回声系统 v2 —— 描边波纹版。
    /// 按 E 键从玩家位置释放扩散波纹，波纹扫过的精灵（非光源物体）
    /// 会显示外描边（默认白色，可自定义），维持一段时间后整体消散。
    ///
    /// 与 v1 的区别：
    /// - 不再在黑暗遮罩上画光波（那样会漏出地板）
    /// - 改为通过全局 shader 参数控制精灵描边 shader (SpriteEchoOutline)
    /// - 时间模型：扩散 → 维持(sustainTime) → 消散(fadeTime)
    ///
    /// 挂载位置：玩家物体上（或跟随玩家的空物体）
    /// 依赖：场景中需要有用 SpriteEchoOutline shader 的描边精灵
    ///      （由 EchoOutlineManager 自动生成）
    /// </summary>
    public class EchoSystem : MonoBehaviour
    {
        /// <summary>
        /// 按 E 释放回声（摇铃）时触发，参数为释放时的玩家世界位置。
        /// 敌人聆听系统等可订阅此事件。
        /// </summary>
        public static event Action<Vector3> OnEchoReleased;

        [Header("按键")]
        [SerializeField] private KeyCode echoKey = KeyCode.E;

        [Header("扩散参数")]
        [Tooltip("波纹扩散速度（世界单位/秒）")]
        [SerializeField] private float expandSpeed = 15f;

        [Tooltip("最大扩散半径（到达后进入维持阶段）")]
        [SerializeField] private float maxRadius = 30f;

        [Tooltip("波纹前沿柔和宽度（精灵被扫到时的过渡宽度，越大越柔）")]
        [SerializeField] private float ringWidth = 1.5f;

        [Header("时间模型")]
        [Tooltip("扩散到最大半径后，描边维持的时间（秒）")]
        [SerializeField] private float sustainTime = 4f;

        [Tooltip("维持结束后，描边消散的时间（秒）")]
        [SerializeField] private float fadeTime = 1.5f;

        [Header("描边外观")]
        [Tooltip("描边颜色（默认白色，可自定义）")]
        [SerializeField] private Color outlineColor = Color.white;

        [Header("冷却")]
        [Tooltip("回声冷却时间（秒）")]
        [SerializeField] private float cooldown = 2f;

        // 全局 shader 属性 ID（通过 Shader.SetGlobalX 设置，所有描边精灵共享）
        private static readonly int EchoCenterID           = Shader.PropertyToID("_EchoCenter");
        private static readonly int EchoRadiusID           = Shader.PropertyToID("_EchoRadius");
        private static readonly int EchoWidthID            = Shader.PropertyToID("_EchoWidth");
        private static readonly int EchoOutlineIntensityID = Shader.PropertyToID("_EchoOutlineIntensity");
        private static readonly int EchoOutlineColorID    = Shader.PropertyToID("_EchoOutlineColor");

        private enum State { Idle, Expanding, Sustaining, Fading }

        private State _state = State.Idle;
        private float _radius;
        private float _intensity;
        private float _stateTimer;
        private Vector2 _center;
        private float _lastEchoTime = -999f;

        private void Start()
        {
            // 初始化：描边关闭
            Shader.SetGlobalFloat(EchoOutlineIntensityID, 0f);
            Shader.SetGlobalColor(EchoOutlineColorID, outlineColor);
            Shader.SetGlobalFloat(EchoWidthID, ringWidth);
        }

        private void Update()
        {
            // 触发
            if (Input.GetKeyDown(echoKey) && _state == State.Idle && Time.time > _lastEchoTime + cooldown)
            {
                StartEcho();
            }

            // 状态机
            switch (_state)
            {
                case State.Expanding:  UpdateExpanding();  break;
                case State.Sustaining: UpdateSustaining(); break;
                case State.Fading:     UpdateFading();     break;
            }

            // 每帧推送全局参数
            Shader.SetGlobalVector(EchoCenterID, new Vector4(_center.x, _center.y, 0f, 0f));
            Shader.SetGlobalFloat(EchoRadiusID, _radius);
            Shader.SetGlobalFloat(EchoWidthID, ringWidth);
            Shader.SetGlobalFloat(EchoOutlineIntensityID, _intensity);
            Shader.SetGlobalColor(EchoOutlineColorID, outlineColor);
        }

        private void StartEcho()
        {
            _state = State.Expanding;
            _radius = 0f;
            _intensity = 1f;
            _stateTimer = 0f;
            _lastEchoTime = Time.time;

            // 记录释放时刻的玩家位置（回声中心固定，不跟随移动）
            Vector3 p = transform.position;
            _center = new Vector2(p.x, p.z);

            // 通知订阅者（敌人聆听等）
            OnEchoReleased?.Invoke(p);
        }

        private void UpdateExpanding()
        {
            _radius += expandSpeed * Time.deltaTime;
            if (_radius >= maxRadius)
            {
                _radius = maxRadius;
                _state = State.Sustaining;
                _stateTimer = 0f;
            }
        }

        private void UpdateSustaining()
        {
            _stateTimer += Time.deltaTime;
            _intensity = 1f; // 维持阶段满强度
            if (_stateTimer >= sustainTime)
            {
                _state = State.Fading;
                _stateTimer = 0f;
            }
        }

        private void UpdateFading()
        {
            _stateTimer += Time.deltaTime;
            // 消散阶段强度从 1 → 0
            _intensity = Mathf.Clamp01(1f - _stateTimer / Mathf.Max(0.0001f, fadeTime));
            if (_stateTimer >= fadeTime)
            {
                _state = State.Idle;
                _intensity = 0f;
            }
        }

        /// <summary>
        /// 外部调用：强制停止回声
        /// </summary>
        public void StopEcho()
        {
            _state = State.Idle;
            _intensity = 0f;
            Shader.SetGlobalFloat(EchoOutlineIntensityID, 0f);
        }

        public bool IsActive => _state != State.Idle;
    }
}
