#ifndef __OP_H__
#define __OP_H__

#include"pmc_types.h"
#include"Fields.h"
#include"Dictionary.h"
#include"TriggerStatus.h"
#define TIME_DELAY_DEFAULT 200
#define TIME_STABLE_DEFAULT 500
#define TIME_ALARM_DEFAULT 500
#define TIME_USE_LAST -1
typedef enum class _OperatorStatusEnum {UNDEFINED,INIT,RUNNING,WARNING,SUCCESS,ALARM,ABORT} OperatorStatusEnum;
typedef TriggerStatus<OperatorStatusEnum> OperatorStatus;
typedef OperatorStatusEnum (*OperatorFunctionPtr)();
typedef OperatorFunctionPtr OperatorCheckFunctionPtr;
typedef OperatorFunctionPtr OperatorCallbackFunctionPtr;

class OperatorNode {
private:
    OperatorCheckFunctionPtr preCheckFunction=NULL;
    OperatorFunctionPtr      execFunction = NULL;
    OperatorCheckFunctionPtr checkFunction = NULL;
    OperatorCheckFunctionPtr alarmCheckFunction = NULL;
    OperatorCallbackFunctionPtr alarmCallbackFunction = NULL;
    OperatorCallbackFunctionPtr resetFunction = NULL;
    //About Setting parameters of times
    long setDelayTime= TIME_DELAY_DEFAULT;
    long setStableTime= TIME_STABLE_DEFAULT;
    long setTriggerAlarmTime= TIME_ALARM_DEFAULT;
    long setTimeout = 0;
    //About elapsewd times
    long elapsedDelayTime=0;
    long elapsedStableTime=0;
    long elapsedTriggerAlarmTime=0;
    long elapsedTriggerWarningTime = 0;
    long elapsedTimeout = 0;
    
    PMCBOOL isInDelay = FALSE;
    OperatorNode* subOpList[MAX_SUB_OP_COUNT] = { 0 };
    short subOpCount=0;
    short subOpIndex=0;
    void doSimpleOperation();
    void simpleMonitor();
    void doOperation();
    
public:
    char name[MAX_NAME_LEN] = { 0 };
    Fields<MAX_PARAM_COUNT> params;
    short paramsCount=0;
    OperatorStatusEnum status=OperatorStatusEnum::INIT;
    
    //char  alarmText[MAX_CONTEXT_LEN]; 错误信息放到OP中，省点空间
    //preserved alarm method
    unsigned char confirm=0;
    unsigned char method=0;
    TriggerStatus<PMCBOOL> isTimeout = FALSE;
public:
    OperatorNode();
    void reset();
    void subscribe(const char* name);
    void subscribe(const char* name, OperatorFunctionPtr execFunction);
    void subscribe(const char* name, OperatorFunctionPtr execFunction,OperatorCheckFunctionPtr preCheckFunction);
    void subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction);
    void subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction,OperatorCheckFunctionPtr alarmCheckFunction);
    void subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction,OperatorCallbackFunctionPtr alarmCallbackFunction);
    void addExec(OperatorFunctionPtr function);
    void addPreCheck(OperatorCheckFunctionPtr function);
    void addCheck(OperatorCheckFunctionPtr function);
    void addAlarmCheck(OperatorCheckFunctionPtr function);
    void addAlarmCallback(OperatorCallbackFunctionPtr function);
    void addReset(OperatorCallbackFunctionPtr function);
    //参数用逗号分割，NULL表示取默认，时间小于0表示取默认
    OperatorNode* setParams(const char* paramString = 0);
    OperatorNode* setTimes(long delayTime = -1, long stableTime = -1, long triggerAlarmTime = -1, long timeout = -1);


    //add sub op
    OperatorNode* addChild();
    OperatorNode* addChild(const char *name);
    //about run time
    void Do();
    void monitor();
    void retryAlarm();
    void resetAlarm();
    void ignoreAlarm(PMCBOOL *first);
};

class COP{
    private:
        //COP();
        Dictionary<OperatorNode,MAX_OP_COUNT> opTree;
        OperatorNode subOpArray[TOTAL_SUB_OP_COUNT];
        int subOpLength=0;
        friend OperatorNode;
    public:
        OperatorNode* current=NULL;
        OperatorNode* currentRoot=NULL;
        PMCBOOL isAborted=FALSE;
        char  alarmText[MAX_CONTEXT_LEN];
    public:
         
        OperatorNode* subscribe(const char* name);
        OperatorNode* subscribe(const char* name, OperatorFunctionPtr execFunction);
        OperatorNode* subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction);
        OperatorNode* subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction);
        OperatorNode* subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction);
        OperatorNode* subscribe(const char* name, OperatorFunctionPtr execFunction, OperatorCheckFunctionPtr preCheckFunction, OperatorCheckFunctionPtr checkFunction, OperatorCheckFunctionPtr alarmCheckFunction, OperatorCallbackFunctionPtr alarmCallbackFunction);
        //根据name查找OperatorNode
        OperatorNode* select(const char* name);
        OperatorStatusEnum monitor_a();
        OperatorStatus& monitor();
        //about alarm deal method
        
        void alarm();
        void warning();
        //重试当前步骤或子步骤
        void retryAlarm(const char *opName=NULL);
        //跳过当前步骤或子步骤，继续往下执行
        void ignoreAlarm(const char* opName = NULL);
        //重新恢复并从头执行当前主动作
        void resetAlarm(const char* opName = NULL);

        void abort();
       
        //不要在OP结点的委托函数中调用reset        
        void reset();
        
        
};
extern COP* OP;
#endif
