#ifndef __DY_PP_H
#define __DY_PP_H
#include "dy_common.h"
#include "lauxlib.h"
#include "lua.h"

#define PARSE_SCRIPT_DIR "/app/script/"
#define LUA_DDEFAULT_ENV "dyutils=require(\"dyutils\") bit=require(\"bit\") lpack=require(\"lua_pack\") cjson=require(\"cjson\") base64=require(\"base64\") syslog=require(\"syslog\") bcd=require(\"bcd\") sqlite3=require(\"lsqlite3\") bnot = bit.bnot band, bor, bxor = bit.band, bit.bor, bit.bxor lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol broker_addr=\"localhost\" broker_port=1883"

#define LUA_EXTEND ".lua"
#define PYTHON_EXTEND ".py"
#define JAVASCRIPT_EXTEND ".js"
typedef enum
{
    TAG_TYPE_NULL,
    TAG_TYPE_INT16,
    TAG_TYPE_UINT16,
    TAG_TYPE_INT32,
    TAG_TYPE_UINT32,
    TAG_TYPE_FLOAT,
    //
    TAG_TYPE_INT16I,
    TAG_TYPE_INT32I,
    TAG_TYPE_UINT16I,
    TAG_TYPE_UINT32I,
    TAG_TYPE_FLOATI,
    //
    TAG_TYPE_INT8,
    TAG_TYPE_UINT8,
    TAG_TYPE_INT64,
    TAG_TYPE_UINT64,
    TAG_TYPE_VLENGTH,
    TAG_TYPE_BITS,
} tag_data_format_e;

// 模板
typedef enum
{
    GW_PROTC_NULL,
    GW_PROTC_DYWL_LORA_V1,
    GW_PROTC_DYWL_RS485_V1,
    GW_PROTC_MODBUS,
    GW_PROTC_DYWL_RTU_V66,
    GW_PROTC_WOOLINK_DTU,
    GW_PROTC_S7_PLC,
} gw_protocol_e;

typedef enum
{
    DATA_TYPE_PROPERTY = 0,
    DATA_TYPE_EVENT,
    DATA_TYPE_SERVICE,
    DATA_TYPE_PERIOD_PROPERTY,
} data_type_e;

typedef struct
{
    int stream_direction; ///<数据流方向 1：直接返回 0：正常流向
    int no_base64;        ///<不需要base64编码 0:需要 1：不需要
    int no_bin;           ///<不需要%02x
} encode_info_t;

typedef struct
{
    char sign_mark[32];              ///< size max 16 bytes
    int offset;                      ///<偏移位置
    tag_data_format_e raw_data_type; ///<采样报文中数据类型
    char *desc;                      ///<关系字段
} mac_info_t;

typedef struct
{
    unsigned int macCnt; ///<位号的长度
    mac_info_t mac[0];   ///<位号指针数组
} mac_info_table_t;

typedef struct
{
    char sign_mark[32]; ///< size max 16 bytes
    char reference_length[32];
    double k;                        ///<位号值矫正系数
    double b;                        ///<位号值矫正偏移
    tag_data_format_e raw_data_type; ///<采样报文中数据类型
} tag_param_t;

typedef struct
{
    int paramCnt;
    tag_param_t param[0];
} tag_param_table_t;

typedef struct
{
    unsigned int instruction_code;
    char identifier[64];          ///<用户参数
    int32_t report_period;        //上报周期
    tag_param_table_t *param_tab; ///<位号指针数组
} tag_cfg_t;
typedef struct
{
    unsigned int tagCnt; ///<位号的长度
    tag_cfg_t tag[0];    ///<位号指针数组
} tag_table_cfg_t;

typedef struct
{
    uint8_t start;
    uint8_t count;
    char sign_mark[32];
} bit_field_t;

typedef struct
{
    char sign_mark[32];
    char reference_length[32];
    tag_data_format_e raw_data_type;
    int sign_val;
    int min;
    int max;
    double k; ///<位号值矫正系数
    double b; ///<位号值矫正偏移
    int dynamic;
    char *desc; ///<关系字段
    int bit_cnt;
    bit_field_t *bit_fields;
} service_param_t;
typedef struct
{
    int32_t paramCnt;
    service_param_t param[0];
} service_param_table_t;
typedef struct
{
    uint8_t instruction_code;
    unsigned int server_period; // ms
    int direction;
    char identifier[64];              ///<用户参数
    int32_t report_period;            //上报周期
    service_param_table_t *param_tab; ///<位号指针数组
    unsigned int dummy[4];            /// for further use
} service_cfg_t;
typedef struct
{
    unsigned int serviceCnt;
    service_cfg_t service[0];
} service_table_t;

typedef struct
{
    char sign_mark[32]; ///< size max 32 bytes
    uint8_t bit_len;
} bit_param_t;

typedef struct
{
    int32_t bitCnt;
    bit_param_t bit[0];
} bit_param_table_t;

typedef struct
{
    char sign_mark[32]; ///< size max 32 bytes
    char reference_length[32];
    double k;                        ///<位号值矫正系数
    double b;                        ///<位号值矫正偏移
    tag_data_format_e raw_data_type; ///<采样报文中数据类型
    int bit_cnt;
    bit_field_t *bit_fields;
} event_param_t;

typedef struct
{
    int32_t paramCnt;
    event_param_t param[0]; ///<位号指针数组
} event_param_table_t;
typedef struct
{
    uint8_t instruction_code;
    char identifier[64];            ///<用户参数
    int32_t report_period;          //上报周期
    event_param_table_t *param_tab; ///<位号指针数组
} event_cfg_t;
typedef struct
{
    unsigned int eventCnt; ///<位号的长度
    event_cfg_t event[0];  ///<位号指针数组
} event_table_t;

struct pp_script_thread_s;

enum script_type
{
    SCRIPT_NONE = 0,
    SCRIPT_PARSER, /// < 只是协议解析部分
    SCRIPT_DEAMON, ///< 常驻脚本
};

typedef enum script_scope
{
    SCRIPT_TEMPLATE = 0, ///< 一个模板启动一个脚本
    SCRIPT_NODE,         ///< 一个设备一个脚本
} script_scope_e;

typedef struct template_cfg_s
{
    char template_id[16];
    gw_protocol_e protocol;             ///<设备协议
    int32_t offline_times;              ///<离线判断时间
    int32_t report_period;              ///<数据上报周期
    int32_t logout_times;               ///< logout 时间，必须恒定=0
    unsigned int communication_timeout; ///<通信超时
    char *parser_url;                   ///<解析脚本下载路径
    char *parser_script;                ///<解析脚本下载路径
    int use_parser_url;                 ///<使用公用解析脚本标志0:代表不用，1代表协议解析用, 2代表常驻
    script_scope_e script_scope;        ///<脚本的作用范围，0 一个模板启动一个脚本  1 一个设备一个脚本
    char *upgrade_url;                  ///<升级脚本下载路径
    char *upgrade_script;               ///<升级脚本路径
    union
    {
        lua_State *lua;
        int python;
    } script;
    mac_info_table_t *mac_tab;                ///< mac信息
    tag_table_cfg_t *tag_tab;                 ///<属性配置
    service_table_t *service_tab;             ///<服务配置
    event_table_t *event_tab;                 ///<事件配置
    struct pp_script_thread_s *script_thread; ///脚本线程结构
} template_cfg_t;

typedef struct
{
    int template_cnt;
    template_cfg_t template[0];
} template_table_t;

// 物模型
// 物模型 属性表

typedef struct
{
    char type[64];
    double thresholdVal;
    char status; ///< 0:未报过,1:UNSET,2:SET
} condition_report_t;

typedef struct
{
    char identifier[64]; ///<用户参数
    char *desc;          ///<关系字段
    double max;          ///<最大值
    double min;          ///<最小值
    ///<此处后面加数据类型描述
    tag_data_format_e raw_data_type;
    condition_report_t condition;
    char *ext_data;
    bool need_calc;
} object_property_cfg_t;

#define LNX_UPVALUES_FUNC "lnx_ALL_UPVALUES"

typedef struct
{
    unsigned int propertyCnt;          ///<位号的长度
    char * lua_script;                 ///<用于加速Lua表达式执行的Lua脚本
    lua_State * luast;                 ///<用于加速Lua表达式执行的Lua结构体
    void * sign_mark;                  ///<用于查找sign_mark与upvalue对应的表
    object_property_cfg_t property[0]; ///<位号指针数组
} object_property_table_t;

// 物模型 服务表
typedef struct object_service_cfg_s
{
    char identifier[64];              ///<用户参数
    char *desc;                       ///<描述
    char method[128];                 ///<描述
    object_property_table_t *pinput;  ///<位号指针数组
    object_property_table_t *poutput; ///<位号指针数组
} object_service_cfg_t;

typedef struct
{
    unsigned int serviceCnt;
    object_service_cfg_t service[0];
} object_service_table_t;

// 物模型 事件表
typedef struct object_service_cfg_s object_event_cfg_t; //事件结构和服务一致
typedef struct
{
    unsigned int eventCnt;       ///<位号的长度
    object_event_cfg_t event[0]; ///<位号指针数组
} object_event_table_t;

// 物模型
typedef struct
{
    char object_model_id[16];
    char product_secret[32];
    object_property_table_t *property_tab; ///<属性配置
    object_service_table_t *service_tab;   ///<服务配置
    object_event_table_t *event_tab;       ///<事件配置
} object_cfg_t;

typedef struct
{
    int object_cnt;
    object_cfg_t object[0];
} object_table_t;

typedef enum
{
    NOT_REPORT = 0, // 需要上报但未上报
    REPORTED,       // 已经上报
    NONEED_REPORT,  // 无需上报
} tag_report_type;
typedef struct
{
    char sn[SN_MAX_LEN];           ///<设备SN，210124001234
    char *tag_node;                ///< tag json
    int tag_len;                   ///< tag长度
    time_t time;                   ///<时间
    tag_report_type report;        ///<数据上报标识，0:需要上报但未上报 1：已上报 2:无需上报
    unsigned char res;             ///<质量码
    char identifier[64];           ///<服务名称
    unsigned int mi;               ///流水号
    data_type_e data_type;         ///<数据类型
    int32_t report_period;         ///<上报周期
    unsigned char other_platform;  ///<第三方平台标记
    unsigned char port;            ///<数据来源端口
    char app_key[MAX_APP_KEY_LEN]; ///<数据来源APP KEY
    char *ext;                     ///<扩展字段
    int id;                        ///< id
    char requester[8];             ///<调用方
} tag_table_t;                     //位号表

typedef struct
{
    struct list_head list;
    tag_table_t tag;
} tag_list_node_t;

typedef struct _app_config_s
{
    char name[32];
    char version[32];
    char *base_url;
    char depend_name[32];
    char cmd[64];
    char check_cmd[32];
    int installed;
} app_config_t;

typedef struct regulate_cmd_backup_s
{
    char sn[SN_MAX_LEN];
    char src_identifier[64];
    int mi;
    int ts;
    char requester[8];
    char data[256];
    int len;
    unsigned char protocol;
} regulate_cmd_backup_t;

typedef struct _period_service_instance_s
{
    struct list_head list;   // 将周期服务实例串起来
    service_cfg_t *pservice; // 周期服务
    char sn[SN_MAX_LEN];     //设备SN，210124001234
    time_t last_send;        // 上次发送时间
    pp_regulate_signal_t rs; //下行数据
    bool period_triggered;   //是否已经触发
} period_service_instance_t;

typedef struct
{
    struct list_head list;   //将待发送数据串起来
    pp_regulate_signal_t rs; //待发送数据
} send_data_instance_t;

static inline int get_format_size(tag_data_format_e format)
{
    switch (format)
    {
    case TAG_TYPE_INT16:
    case TAG_TYPE_UINT16:
    case TAG_TYPE_INT16I:
    case TAG_TYPE_UINT16I:
    case TAG_TYPE_INT8:
    case TAG_TYPE_UINT8:
        return 2;
    case TAG_TYPE_INT32:
    case TAG_TYPE_UINT32:
    case TAG_TYPE_FLOAT:
    case TAG_TYPE_FLOATI:
    case TAG_TYPE_INT32I:
    case TAG_TYPE_UINT32I:
        return 4;
    case TAG_TYPE_INT64:
    case TAG_TYPE_UINT64:
        return 8;

    default:
        return 0;
    }
}

extern int load_nodes_cfg(nodes_cfg_table_t **p_nodes_cfg, const char *cfg_file);
extern int load_templates_cfg(template_table_t **p_template_table, const char *cfg_file);
extern int load_objects_cfg(object_table_t **p_object_table, const char *cfg_file);
extern template_cfg_t *pp_find_template(template_table_t *template_table, char *ptemplate_id);
extern object_cfg_t *find_object_by_id(object_table_t *object_table, char *object_model_id);

/*
 * 构造用于加速Lua表达式执行的Lua脚本
 * 会修改`scfg->poutput->lua_script指针
 */
extern int build_property_luaexp(const template_table_t * ptemp,
    object_service_cfg_t * scfg, const char * object_mid);

#endif
