#pragma once

#include "myBase.h"
#include "myTask.h"
#include <vector>
#include <string>
#include <map>


#define MSG_SIZE 2048 // 消息队列消息大小
#define MSG_NUM  8 // 消息队列消息个数


#define TIMER_NUM 3 // 定时器个数
// 通用定时器事件
#define EV_TIMER1                   (0x01 << 0) // 定时器1
#define EV_TIMER2                   (0x01 << 1) // 定时器2
#define EV_TIMER3                   (0x01 << 2) // 定时器3

// 通讯线程事件
#define EV_COM_RX_IEC               (0x01 << 3) // 收到IEC消息事件
#define EV_COM_RX_SELF_PTL          (0x01 << 4) // 收到ICP67消息事件

// iec线程事件
#define EV_IEC_RX_COM               (0x01 << 3) // 收到i端口消息事件


// icp67线程事件
#define EV_SELF_PTL_RX_COM          (0x01 << 3) // 收到端口消息事件
// #define EV_SELF_PTL_RX_IEC    (0x01 << 4) // 收到iec消息事件


// webserver线程事件


// iec61850m线程事件


// datacenter线程事件

// 消息队列枚举
typedef enum
{
    ENUM_MQ_COM_TO_IEC,         // 通讯线程到iec线程消息队列
    ENUM_MQ_IEC_TO_COM,         // iec线程到通讯线程消息队列
    ENUM_MQ_COM_TO_SELF_PTL,    // 通讯线程到icp67线程消息队列
    ENUM_MQ_SELF_PTL_TO_COM,    // icp67线程到通讯线程消息队列

    ENUM_MQ_MAX
}enun_msg_queue;


// 应用枚举
typedef enum
{
    ENUM_APP_CMD,           // 命令行应用
    ENUM_APP_DATACENTER,    // 数据中心应用
    ENUM_APP_COMM,          // 通讯通道应用
    ENUM_APP_COM_SCAN,      // 通讯扫描应用
    ENUM_APP_IEC,           // iec101104应用
    ENUM_APP_SELF_PTL,      // icp67应用
    ENUM_APP_WEB_SERVER,    // web服务器应用
    ENUM_APP_IEC61850M,      // iec61850m应用

    ENUM_APP_MAX
}enum_app;
 

// 通讯枚举
typedef enum
{
    ENUM_COMM_TCP_S_0,      // 上位机TCP服务器
    ENUM_COMM_TCP_C_0,      // 连接FTU的TCP客户端
    ENUM_COMM_UART_0,       // 连接FTU的UART，接收FTU的数据
    ENUM_COMM_TCP_S_1,      // 对上的101104 TCP服务器
    ENUM_COMM_MAX
}enum_comm;

// 网络枚举
typedef enum
{
    ENUM_TCP_SERVER_0,
    ENUM_TCP_CLIENT_0,
    ENUM_TCP_SERVER_1, // 104s
    ENUM_TCP_MAX
}enum_tcp;

// 串口枚举
typedef enum
{
    ENUM_UART_0,
    ENUM_UART_MAX
}enum_uart;



// 应用消息队列结构体
typedef struct
{
    const char *name;                   // 消息队列名称
    uint32_t msg_size;                  // 消息大小
    uint32_t msg_num;                   // 消息个数
    stru_task_msg_queue_t p_msg_queue;  // 消息队列指针
}stru_app_msg_queue;


// 通讯收发数据结构体
typedef struct
{
    uint16_t rx_len;                    // 接收数据长度
    uint16_t tx_len;                    // 发送数据长度
    uint8_t rx[MSG_SIZE];               // 接收数据     
    uint8_t tx[MSG_SIZE];               // 发送数据     
}stru_rtx_data;


// 消息结构
#pragma pack(1)
typedef struct
{
    uint32_t interface;     // 接口类型
    uint16_t len;           // 数据长度
    uint8_t backup[2];      // 备用字节
    uint8_t data[0];        // 数据
}stru_msg_head;
#pragma pack()



// icp67协议头
#pragma pack(1)
typedef struct
{
    uint8_t head1;      // 0x67
    uint16_t len;       // 数据长度
    uint8_t head2;      // 0x67
    uint8_t data[0];    // 数据
}stru_icp67_head;
#pragma pack()

// iec协议头
#pragma pack(1)
typedef struct
{
    uint8_t head;       // 0x68
    uint8_t data[0];    // 数据
}stru_iec_head;
#pragma pack()

// 协议头联合体
typedef union
{
    stru_icp67_head icp67;
    stru_iec_head iec;
}stru_protocol_head;


// 应用初始化函数指针类型
typedef int (*app_init_cb)(void *arg);

// 应用线程函数指针类型
typedef void * (*app_func_cb)(void *arg);

// 应用结构体
typedef struct
{
    const char *name;                       // 应用名称
    uint32_t app_id;                        // 应用ID
    app_init_cb app_init1;                  // 应用初始化函数1
    app_init_cb app_init2;                  // 应用初始化函数2
    app_func_cb fun_cb;                     // 应用线程函数
    void *arg;                              // 应用线程函数参数
    pthread_t thread;                       // 应用线程句柄
    stru_task_event_t p_event;              // 应用事件
    stru_rtx_data rtx;                      // 应用收发数据结构体
    uint32_t timer_arg[TIMER_NUM];          // 应用定时器参数
    stru_task_timer_t p_timer[TIMER_NUM];   // 应用定时器指针
    uint32_t run_cnt;                       // 应用运行计数
}stru_app;


// 消息队列指针获取函数，根据消息队列ID获取消息队列指针
stru_app_msg_queue *app_get_msg_queue_ptr(uint32_t mq_id);

// 应用指针获取函数，根据应用ID获取应用指针
stru_app *app_get_ptr(uint32_t app_id);

// 命令行应用初始化与线程函数声明
extern int app_cmd_init1(void *arg);
extern int app_cmd_init2(void *arg);
extern void *app_cmd(void *arg);

// 数据中心应用初始化与线程函数声明
extern int app_datacenter_init1(void *arg);
extern int app_datacenter_init2(void *arg);
extern void *app_datacenter(void *arg);

// 通讯转发应用初始化与线程函数声明
extern int app_com_scan_init1(void *arg);
extern int app_com_scan_init2(void *arg);
extern void *app_com_scan(void *arg);

// iec101104应用初始化与线程函数声明
extern int app_iec_init1(void *arg);
extern int app_iec_init2(void *arg);
extern void *app_iec(void *arg);

// icp67应用初始化与线程函数声明
extern int app_self_ptl_init1(void *arg);
extern int app_self_ptl_init2(void *arg);
extern void *app_self_ptl(void *arg);

// 通讯通道应用初始化与线程函数声明
extern int app_com_channel_init1(void *arg);
extern int app_com_channel_init2(void *arg);
extern void *app_com_channel(void *arg);

// web服务器应用初始化与线程函数声明
extern int app_web_server_init1(void *arg);
extern int app_web_server_init2(void *arg);
extern void *app_web_server(void *arg);

// iec61850m应用初始化与线程函数声明
extern int app_iec61850m_init1(void *arg);
extern int app_iec61850m_init2(void *arg);
extern void *app_iec61850m(void *arg);

// icp67线程设置通道类型
void self_ptl_set_interface(uint32_t interface);

// 通讯通道获取接口类型，通过通道ID获取
uint32_t com_channel_interface_get(uint32_t comm_id);

// 通讯转发线程收到协议待发送的数据
extern void com_recv_data(uint32_t itfs, const uint8_t *p_rx, uint16_t rx_len);


// 信号控制枚举
enum SIGNAL_CTRL_TYPE
{
    NONE,               // 无
    DIRECT_NORMAL,      // 直控
    SBO_NORMAL,         // 选控
};

// 信号控制步骤枚举
enum SIGNAL_CTRL_STEP
{
    READY,              // 准备
    SELECT,             // 选择
    DIRECT,             // 执行
    CANCEL,             // 取消
};

// 数据中心信号控制结构体
typedef struct
{
    uint8_t step:2;     // 控制步骤
    uint8_t type:2;     // 控制类型
    uint8_t backup:4;   // 备用字节
    uint8_t data_type;  // 数据类型
    void *p_data;       // 数据指针
}stru_signal_ctrl;

typedef struct
{
    double min;          // 最小值
    double max;          // 最大值
    double step;         // 步长
    std::string unit;   // 单位
    void *p_default;    // 默认值
}stru_signal_param;

typedef void (*signal_change_cb)(std::string saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, void *p_data);



// 数据中心out信号注册接口
int dc_signal_out(const std::string &saddr, const std::string &desc, uint8_t data_type, void *p_data);

// 数据中心in信号注册并链接out信号接口
int dc_signal_in(const std::string &saddr, const std::string &desc, const std::string &link_saddr, uint8_t data_type, void **p_data);

// 数据中心参数信号注册接口
int dc_signal_param(const std::string &saddr, const std::string &desc, uint8_t data_type, const stru_signal_param &param, uint8_t ctrl_type, void *p_data, signal_change_cb cb);

// 数据中心参数链接信号接口
int dc_signal_param_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb);

// 数据中心参数设置接口
int dc_signal_param_set_val(const std::string &saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, void *p_data);

// 数据中心遥控信号注册接口
int dc_signal_yk(const std::string &saddr, const std::string &desc, uint8_t data_type, uint8_t ctrl_type, void *p_data, signal_change_cb cb);

// 数据中心遥控信号链接接口
int dc_signal_yk_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb);

// 数据中心遥控控制接口
int dc_signal_yk_set_status(const std::string &saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, void *p_data);

// 数据中心获取out信号信息接口
int dc_get_out_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, void **p_data);

// 数据中心获取in信号信息接口
int dc_get_in_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, void **p_data);

// 数据中心获取参数信号信息接口
int dc_get_param_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param &param, uint8_t &ctrl_type, void **p_data);

// 数据中心获取遥控信号信息接口
int dc_get_yk_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, uint8_t &ctrl_type, void **p_data);

// 数据中心获取信号值字符串接口
std::string dc_get_signal_val(void *p_data, uint8_t data_type);

// 数据中心设置信号值字符串接口
int dc_set_out_signal_val(const std::string &saddr, void *set_data);

// 数据中心根据数据类型ID获取数据类型字符串接口
std::string dc_get_data_type_str_by_id(uint8_t data_type);

// 数据中心根据数据类型字符串获取数据类型ID接口
uint8_t dc_get_data_type_id_by_str(const std::string &data_type_str);


