
/*********************************************************************
* 版权所有 (C)2019, 深圳多游开发团队。
* 
* 文件名称： // FSMSystem.cs
* 内容摘要： // 该文件是 状态机的管理类
* 其它说明： // 
* 当前版本： // V0.1
* 作    者： // Will.Wang
* 创建日期： // 2019/06/04
* 
* 修改记录1：// 修改历史记录，包括修改日期、修改者及修改内容
*    修改日期：
*    版 本 号：
*    修 改 人：
*    修改内容： 
* 修改记录2：…
**********************************************************************/
using System.Collections.Generic;
using UnityEngine;

public class FSMSystem
{
    private List<FSMState> states = new List<FSMState>();

    private int currentStateID;
    public int CurrentStateID { get { return currentStateID; } }
    private FSMState currentState;
    public FSMState CurrentState { get { return currentState; } }

    public int m_Sign;
    public int sign => m_Sign;
    
    private FSMState m_DefaultState;
    
    public FSMSystem()
    {
     
    }

    public void Update()
    {
        if (currentState == null)
        {
            if (m_DefaultState == null)
            {
                m_DefaultState = this.states.Count > 0 ? states[0] : null;
            }
            
            currentState = m_DefaultState;
            
            if (currentState == null)
            {
                Debug.LogError("default state == null");
                return;
            }
            else
            {
                currentState.DoBeforeEntering();
            }
        }

        currentState.Update();

        foreach (Transition transition in currentState.transMap)
        {
            if (transition != null)
            {
                if (transition.meedCondition())
                {
                    this.PerformTransition(transition);
                    break;
                }
                else if (transition.meedSign(m_Sign))
                {
                    m_Sign = 0;
                    this.PerformTransition(transition);
                    break;
                }
            }
        }
    }

    public void SetDefaultState(FSMState s)
    {
        m_DefaultState = s;
    }
    
    /// <summary>
    /// 添加状态
    /// </summary>
    /// <param name="s"></param>
    public void AddState(FSMState s)
    {
        if (s == null)
        {
            Debug.LogError("FSM ERROR: Null reference is not allowed");
            return;
        }

/*        if (states.Count == 0)
        {
            states.Add(s);
            currentState = s;
            currentStateID = s.ID;
            return;
        }*/
        foreach (FSMState state in states)
        {
            if (state == null)
            {
                Debug.LogError("state == null");
                continue;
            }
            if (state.ID == s.ID)
            {
                Debug.LogError("FSM ERROR: Impossible to add state " + s.ID.ToString() +
                               " because state has already been added");
                return;
            }
        }
        states.Add(s);
    }
    /// <summary>
    /// 删除状态
    /// </summary>
    /// <param name="id"></param>
    public void DeleteState(int id)
    {
        if (id == FSMState.NullStateID)
        {
            Debug.LogError("FSM ERROR: NullStateID is not allowed for a real state");
            return;
        }
        foreach (FSMState state in states)
        {
            if (state.ID == id)
            {
                states.Remove(state);
                return;
            }
        }
        Debug.LogError("FSM ERROR: Impossible to delete state " + id.ToString() +
                       ". It was not on the list of states");
    }

    public void InputSign(int sign)
    {
        this.m_Sign = sign;
    }
    
    /// <summary>
    /// 状态切换
    /// </summary>
    /// <param name="trans"></param>
    public void PerformTransition(Transition trans)
    {
        if (trans == null)
        {
            Debug.LogError("FSM ERROR: NullTransition is not allowed for a real transition");
            return;
        }

        int id = trans.toState;
        if (id == FSMState.NullStateID)
        {
            Debug.LogError("FSM ERROR: State " + currentStateID.ToString() + " does not have a target state " +
                           " for transition " + trans.ToString());
            return;
        }

        currentStateID = id;
        foreach (FSMState state in states)
        {
            if (state.ID == currentStateID)
            {
                currentState.DoBeforeLeaving();

                currentState = state;

                currentState.DoBeforeEntering();
                break;
            }
        }

    } 
}