#pragma once

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef MY_GET_DATA_WITH_TYPE 
#define MY_GET_DATA_WITH_TYPE(p, type) (*(type *)(p))
#endif


#ifndef MY_SET_DATA_WITH_TYPE 
#define MY_SET_DATA_WITH_TYPE(p, q, type) (*(type *)(p) = *(type *)(q))
#endif


enum
{
    _MMS_M_EVENT_ALL_CALL,
    _MMS_M_EVENT_GI_CALL,
    _MMS_M_EVENT_CO_SELECT,
    _MMS_M_EVENT_CO_DIRECT,
    _MMS_M_EVENT_CO_CANCEL,
    _MMS_M_EVENT_AO_READ,
    _MMS_M_EVENT_AO_WRITE,
    _MMS_M_EVENT_END
};

enum 
{
    _MMS_M_data_type_unknown = 0,
    _MMS_M_data_type_bool,
    _MMS_M_data_type_int8,
    _MMS_M_data_type_int16,
    _MMS_M_data_type_int32,
    _MMS_M_data_type_int64,
    _MMS_M_data_type_uint8,
    _MMS_M_data_type_uint16,
    _MMS_M_data_type_uint32,
    _MMS_M_data_type_uint64,
    _MMS_M_data_type_float,
    _MMS_M_data_type_double,
    _MMS_M_data_type_string,
    _MMS_M_data_type_end
};

#define MMS_M_STR_LEN 64
#define MMS_M_REF_LEN 128

#define MMS_M_ON_LINE 1
#define MMS_M_OFF_LINE 0


#define MMS_M_DEBUG_PRINT_OFF 0
#define MMS_M_DEBUG_PRINT_ON 1

// typedef union 
// {
//     bool b;
//     int8_t c;
//     int16_t s;
//     int32_t l;
//     uint8_t cu;
//     uint16_t su;
//     uint32_t lu;
//     float f;
// }un_value;


typedef struct
{
    char saddr[MMS_M_STR_LEN];
    char desc[MMS_M_STR_LEN];
    uint8_t data_type;
    void *p_data;
}stru_mms_m_gen_signal;

typedef struct
{
    stru_mms_m_gen_signal sig;
    uint8_t ctrl_type;
}stru_mms_m_ctrl_signal;
    
typedef struct
{
    stru_mms_m_gen_signal sig;
    uint8_t ctrl_type;
    double min;
    double max;
    double step;
    char unit[MMS_M_STR_LEN];
    void *p_default;
}stru_mms_m_param_signal;

typedef struct 
{
    uint16_t st_num;
    uint16_t mx_num;
    uint16_t co_num;
    uint16_t ao_num;
    stru_mms_m_gen_signal *p_st_sig;
    stru_mms_m_gen_signal *p_mx_sig;
    stru_mms_m_ctrl_signal *p_co_sig;
    stru_mms_m_param_signal *p_ao_sig;
}stru_mms_m_config;


typedef struct 
{
    int app_fd;                         // 61850客户端句柄
    char ied[MMS_M_STR_LEN];        // ied名称
    char name[MMS_M_STR_LEN];       // 信号名
    int value_type;                     // 数据类型
    // void *p_val;                        // 设置值    
    char val[128];
    // char val_str[MMS_M_STR_LEN];    // 字符串类型的值
    int ctrl_type;                      // 遥控类型
    int set_zone;                       // 定值区
    void (*p_func)(void *arg, int ret); // 设置回调函数
    // void *arg;                          // 回调函数参数     
}stru_mms_m_event;



typedef struct
{
    int year;
    int mon;
    int day;
    int hour;
    int min;
    int sec;
    int msec;
}stru_mms_m_time;

typedef struct
{
    int app_fd;
    int reason;
    int type;
    int quality;
    char name[MMS_M_STR_LEN];
    char desc[MMS_M_STR_LEN];
    char reference[MMS_M_REF_LEN];
    void *p_value;
    stru_mms_m_time time;
}stru_mms_m_out_value;

typedef void (*mms_m_out_status_cb)(int app_fd, int status);
typedef void (*mms_m_out_value_cb)(stru_mms_m_out_value *p_value);



int mms_m_out_init(const char *config_path, int debug_print_flag, uint32_t connectionTimeout);

int mms_m_out_get_signal_info(int app_fd, stru_mms_m_config *p_config);

int mms_m_out_get_connect_status(int fd, mms_m_out_status_cb p_func);

int mms_m_out_debug_print_swicth(int id, int debug_print_flag);

int mms_m_out_do_set_yk_or_param(stru_mms_m_event *p_event);

int mms_m_out_read_params(int app_fd);
int mms_m_out_read_param(int app_fd, const char *param_name);

int mms_m_out_get_value(int app_fd, mms_m_out_value_cb p_func);
char *mms_m_out_reason_str(int reason);


void *mms_m_create_data_ptr(uint8_t type);
int mms_m_set_data_value(void *srt, void *dst, uint8_t type);
int mms_m_get_data_value_str(void *data, uint8_t type, char *str);

#ifdef __cplusplus
}
#endif

