#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<time.h>
#include<sys/time.h>

#include <string>
#include <vector>
#include <semaphore.h>
#include <pthread.h>

#include "iec61850_client.h"
#include "mms_m_parse_cfg.h"

#define COLOR_RESET     "\033[0m"
#define COLOR_RED       "\033[31m"
#define COLOR_GREEN     "\033[32m"
#define COLOR_YELLOW    "\033[33m"
#define COLOR_BLUE      "\033[34m"
#define COLOR_MAGENTA   "\033[35m"
#define COLOR_CYAN      "\033[36m"
#define COLOR_WHITE     "\033[37m"


/* 获取当前时间字符串 */
#define __CURRENT_TIME__ \
    ({ \
        struct timeval __tv; \
        gettimeofday(&__tv, NULL); \
        struct tm *__tm = localtime(&__tv.tv_sec); \
        static char __buf[84]; \
        snprintf(__buf, sizeof(__buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d", \
            __tm->tm_year + 1900, __tm->tm_mon + 1, __tm->tm_mday, \
            __tm->tm_hour, __tm->tm_min, __tm->tm_sec, (int)(__tv.tv_usec / 1000)); \
        __buf; \
    })

#define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

#define LOG(color, level, fmt, ...) \
    do{\
        printf("%s[%s] [%s: %s, %u] " fmt COLOR_RESET "\n", \
            color, level, __CURRENT_TIME__, __SHORT_FILE__, __LINE__, ##__VA_ARGS__); \
    }while (0)


#define LOG_I(fmt, ...)  LOG(COLOR_WHITE, "INFO", fmt, ##__VA_ARGS__)
#define LOG_E(fmt, ...)  LOG(COLOR_RED, "ERROR", fmt, ##__VA_ARGS__)    


#define MMS_M_THREAD_RUN_TM 100 //线程运行间隔时间 100ms
#define MMS_M_TIMER_T0  (120 * (MMS_M_THREAD_RUN_TM * 10 / 1000))     // 定时器T0 120秒
#define MMS_M_TIMER_T1  (60 * (MMS_M_THREAD_RUN_TM * 10 / 1000))      // 定时器T1 60秒
#define MMS_M_TIMER_T2  (15 * (MMS_M_THREAD_RUN_TM * 10 / 1000))      // 定时器T2 15秒
#define MMS_M_TIMER_T3  (20 * (MMS_M_THREAD_RUN_TM * 10 / 1000))      // 定时器T3 20秒


enum
{
    _MMS_M_TIMER_T0,
    _MMS_M_TIMER_T1,
    _MMS_M_TIMER_T2,
    _MMS_M_TIMER_T3,
    _MMS_M_TIMER_END
};


#define EVENT_QUEUE_SIZE 64


typedef struct
{
    bool running;
    uint32_t cnt;
    uint32_t tmout;
    void (*p_func)(void *);
    void *arg;
}stru_mms_m_timer;

typedef struct
{
    uint8_t w_ptr;
    uint8_t r_ptr;
    uint8_t size;
    uint8_t num;
    stru_mms_m_event event[EVENT_QUEUE_SIZE];        // 事件队列，内部处理，外部也可推入事件
}stru_event_queue;

typedef struct
{
    std::string ip;                                     // 服务器IP地址
    int port;                                           // 服务器端口号

    bool running_init;  
    sem_t sem;                                       // 回调信号量
    pthread_t pthread_task;
    IedConnection con;                                 // 连接到服务器的ied
    IedConnectionState con_state;                      // 连接状态
    IedConnectionState old_con_state;                  // 上一次的连接状态
    stru_mms_m_timer timer[_MMS_M_TIMER_END];  // 定时器

    stru_mms_m_event event;                        // 事件    
    stru_event_queue event_queue;            // 事件队列

    mms_m_out_status_cb out_status_cb;               // 链接状态回调
    std::vector<mms_m_out_value_cb> out_cb_lists;        // 输出回调列表
}stru_mms_m_run;


typedef struct
{
    std::string do_name;                                    // 数据对象名称
    std::vector<stru_point_item *> p_do_vec;            // 指向DO的指针集合
    // stru_point_item *p_do;                             // 指向DO的指针
}stru_dobj;

typedef struct
{
    std::string ln_name;                                // 逻辑节点名称 
    std::vector<stru_dobj> dobjs;                       // 数据对象集合
}stru_lnode;

typedef struct
{
    std::string ld_name;                                // 逻辑设备名称
    std::vector<stru_lnode> lnodes;                     // 逻辑节点集合
}stru_ldev;


typedef struct
{
    std::string ref;                                   // 描述
    int reason;                                        // 原因
    // stru_point_item *p_do;                             // 指向DO的指针
    std::vector<stru_point_item *> *p_do_vec;           // 指向DO的指针集合
}stru_member;

typedef struct 
{
    std::string dataset_name;                           // 数据集名称
    std::string dataset_ref;                            // 数据集描述
    std::vector<stru_member> members;                   // 数据集成员集合
}stru_ln_dataset;


typedef struct
{
    std::string rpt_ref;                                // 报告描述
    std::string rpt_ref_with_no;                        // 报告描述+编号
    std::string ds_ref;                                 // 数据集描述
    int type;                                           // 类型
    ClientReportControlBlock rcb;                       // 报告控制块
    void *p_app;                                        // 应用层报告指针
    stru_ln_dataset *p_dataset;                         // 指向数据集的指针
}stru_ln_rpt;


typedef struct
{
    std::string ref;                                    // 数据集描述
    std::string ld_name;                                // 逻辑设备名称
    std::string ln_name;                                // 逻辑节点名称
    std::vector<stru_ln_dataset> ln_datasets;              // 数据集集合
    std::vector<stru_ln_rpt> ln_rpts;                      // 报告集合
}stru_ld_dataset;


typedef struct
{
    int obj_fd;
    uint32_t connectionTimeout;                         // 连接超时时间
    std::string cfg_path;                               // 配置文件路径
    stru_cfg *p_cfg;                                    // 配置解析后指针

    int debug_print_flag;                               // 调试打印标志

    std::string ied_name;                               // ied名称
    MmsValue *param_zone;                               // 参数定值区
    MmsValue *set_confirm;                              // 设置确认
    
    stru_mms_m_run run;                             // 运行时数据结构

    std::vector<stru_ldev> ldevs;                       // 逻辑设备集合
    std::vector<stru_ld_dataset> ld_datasets;           // 数据集集合
}stru_mms_m_obj;




