using System;
using System.Collections.Generic;
using MrWu.Debug;

namespace GlobalSever.FSM
{
    /// <summary>
    /// 有限状态机状态
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public abstract class FSMState<T> where T : class
    {
        /// <summary>
        /// 状态类型
        /// </summary>
        public virtual Type StateType => this.GetType();

        public virtual int StateId { get; protected set; } = -1;

        internal FSMState<T> NextState;
        internal FSMState<T> LastState;

        /// <summary>
        /// 持续时间, 单位毫秒
        /// </summary>
        public int RunDuratime { get; set; }

        /// <summary>
        /// 延迟执行任务列表
        /// </summary>
        private List<DelayedAction> _delayedActions = new List<DelayedAction>();

        public FSMState()
        {

        }
        
        public FSMState(int stateId)
        {
            StateId = stateId;
        }

        /// <summary>
        /// 有限状态机初始化时调用
        /// </summary>
        /// <param name="fsm"></param>
        public virtual void OnInit(FSM<T> fsm)
        {
            RunDuratime = 0;
        }
        
        /// <summary>
        /// 有限状态机进入时调用
        /// </summary>
        /// <param name="fsm"></param>
        public virtual void OnEnter(FSM<T> fsm)
        {
            Debug.Log($"{StateType.Name} OnEnter");
        }

        /// <summary>
        /// 轮训
        /// </summary>
        /// <param name="fsm">有限状态机</param>
        /// <param name="interval">时间间隔</param>
        public virtual void Update(FSM<T> fsm, float interval)
        {
            // 处理延迟执行的任务
            if (_delayedActions.Count > 0)
            {
                for (int i = _delayedActions.Count - 1; i >= 0; i--)
                {
                    var delayedAction = _delayedActions[i];
                    delayedAction.RemainingMsTime -= (int)interval;
                    if (delayedAction.RemainingMsTime <= 0)
                    {
                        delayedAction.Action?.Invoke();
                        _delayedActions.RemoveAt(i);
                    }
                }
            }
        }

        /// <summary>
        /// 有限状态机离开时调用
        /// </summary>
        /// <param name="fsm"></param>
        public virtual void OnLeave(FSM<T> fsm)
        {
            RunDuratime = 0;
            ClearDelayedActions();
            Debug.Log($"{StateType.Name} OnLevel");
        }

        /// <summary>
        /// 有限状态机销毁时调用
        /// </summary>
        /// <param name="fsm"></param>
        public virtual void OnDestroy(FSM<T> fsm)
        {
        }

        /// <summary>
        /// 切换到下一个状态
        /// </summary>
        public void ChangeNextState(FSM<T> fsm, int delayTime = 0)
        {
            if (NextState != null)
                ChangeState(fsm, NextState.StateType, delayTime);
        }

        /// <summary>
        /// 切换状态
        /// </summary>
        public void ChangeState(FSM<T> fsm, FSMState<T> state)
        {
            ChangeState(fsm, state.StateType);
        }

        /// <summary>
        /// 切换状态
        /// </summary>
        /// <param name="fsm"></param>
        /// <typeparam name="TState"></typeparam>
        public void ChangeState<TState>(FSM<T> fsm, int delayTime = 0) where TState : FSMState<T>
        {
            ChangeState(fsm, typeof(TState), delayTime);
        }

        /// <summary>
        /// 切换状态
        /// </summary>
        /// <param name="fsm"></param>
        /// <param name="stateType"></param>
        public void ChangeState(FSM<T> fsm, Type stateType, int delayTime = 0)
        {
            FSM<T> fsmImplement = (FSM<T>)fsm;

            if (stateType == null)
            {
                throw new Exception("State type is invalid.");
            }

            if (!typeof(FSMState<T>).IsAssignableFrom(stateType))
            {
                throw new Exception($"State type '{stateType}' is invalid.");
            }

            fsmImplement.ChangeState(stateType, delayTime);
        }

        /// <summary>
        /// 延迟执行Action
        /// </summary>
        /// <param name="action">要执行的Action</param>
        /// <param name="delayMs">延迟时间，单位毫秒</param>
        public void DelayedExecute(Action action, int delayMs)
        {
            if (action == null || delayMs <= 0)
                return;

            _delayedActions.Add(new DelayedAction
            {
                Action = action,
                RemainingMsTime = delayMs
            });
        }

        /// <summary>
        /// 清除所有延迟执行的任务
        /// </summary>
        public void ClearDelayedActions()
        {
            _delayedActions.Clear();
        }
    }

    /// <summary>
    /// 延迟执行任务
    /// </summary>
    internal class DelayedAction
    {
        public Action Action { get; set; }
        /// <summary>
        /// 剩余时间（ms）
        /// </summary>
        public int RemainingMsTime { get; set; }
    }
}