#pragma once
#include "receiver.hpp"
#include <string>
#include <iostream>
#include <regex>
#include <functional>

using namespace ns_mess;


#define CLASS_INFO \
  virtual std::string __className() { \
    std::string nameBuffer( __FUNCTION__ ); \
    std::smatch result; \
    std::regex pattern( "(\\w+)::" ); \
    std::regex_search( nameBuffer, result, pattern ); \
    return result[1]; \
  }

//typedef std::function<string ()> StateFunc;
#define CLASSNAME __className()
#define FUNCNAME __func__
#define CLASSFUNCNAME __className() + "_" + __func__
#define DESCRIBE(str) str,CLASSNAME,FUNCNAME

struct RUN_FLAG
{
    string func;
    string step;
    bool flag;
};

class  __declspec(dllexport) CFsmBase
{
    //û���¸�Step����
    #define STEP_NULL  [&](CEventBase const& msg) { return true; }
    //Stepִ�����ִ�еĺ���
    #define STEP_FUNC(func)  [&](CEventBase const& msg) {func; return true; }
    //��״̬�����¸�Step����
    #define NEXT_STEP(step) [&](CEventBase const& msg) {m_ThisSender().Send(step); return true; }
    //����״̬����Step����
    #define NEXT_STEP_EXTERNAL(step) [&](CEventBase const& msg) {m_ExternalSender().Send(step); return true; }

private:
    CLASS_INFO;

    static std::mutex g_FlagMutex;
    static std::vector<RUN_FLAG> m_vecRunFlag;
    
    CSender m_MsgSender;
    void SetSender(CSender _sender);
public:
    static void SetFlag(string func, string step);
    static bool Getflag(string func, string step);
    static void ClearFlag(string func);

protected:
    StateFunc m_StateCurrent;
    CReceiver m_MsgReceiver;

    CFsmBase(CFsmBase const&) = delete;
    CFsmBase& operator=(CFsmBase const&) = delete;
    CFsmBase();

    //����״̬
    virtual string Idle() = 0;
    //У׼״̬
    virtual string Calib() = 0;
    //���״̬
    virtual string Programming() = 0;
    //���״̬
    virtual string Diagnosis() = 0;
    //�Զ��̾�״̬
    virtual string AutoBond() = 0;
    //�ֶ�����״̬
    virtual string ManualOperation() = 0;


public:
    bool Init(CSender _sender);

    void StopFsm();        //ֹͣ����
    void ExitFsm();        //�˳� 
    void RunFsm();         //��ʼ����

    CSender m_ThisSender();//��״̬��������Ϣ
    
    CSender m_ExternalSender(); //���ⲿ״̬������Ϣ

    template <class _Fx, class... _Types>
    void SetState(_Fx&& _Func, _Types&&... _Args)
    {
        StateFunc m_chState = _Binder<_Unforced, _Fx, _Types...>(_STD forward<_Fx>(_Func), _STD forward<_Types>(_Args)...);
        m_ThisSender().Send(ChangeState(m_chState));
    }
   
};