#ifndef __LC_DISCOVER_H__
#define __LC_DISCOVER_H__

#include <sys/time.h>
#include <sys/timerfd.h>
#include "dy_utils/hash_intptr.h"

#define CCLC_DISCOVER_CHANNEL_NAME  "CCLCDISC-V0.1"
#define CHAR_BASE_NUM 64
#define CCLC_AVLID_TIME 10 //有效时间
#define SPILITE_CHAR 's'

#define DISCOVERY_LC_UDP_PORT  5355
#define DISCOVERY_EMS_UDP_PORT 5356
#define DISCOVERY_TYPE_EMS   0x807ffa81
#define DISCOVERY_TYPE_LC    0x807ffa82
#define DISCOVERY_TYPE_VLC   0x807ffa83

typedef struct disc_message_t {
    unsigned int       gw_type;           /* DISCOVERY_TYPE_EMS or DISCOVERY_TYPE_LC */
    char               dmi_sn[32];        /* Gateway SN for CC or LC */
    unsigned short     dmi_type;          /* type of payload message */
    unsigned short     dmi_len;           /* length of payload message */
    unsigned char      dmi_data[0];       /* payload data, variable length */
} disc_msg;

typedef struct disc_cfginfo_t {
    char               sn[32];            /* gateway SN */
    char               name[64];          /* name of device */
    char               no[64];            /* device 编号 */
    unsigned int       devtype;           /* gateway type, DISCOVERY_TYPE_EMS/DISCOVERY_TYPE_LC */
    int                disabled;          /* whether the device is disabled */
    char               ipaddr[20];        /* ip address for EMS/LC */
} disc_cfginfo;

typedef struct disc_devinfo_t {
    time_t             timestamp;         /* last time message received timestamp */
    unsigned int       devtype;           /* gateway type, DISCOVERY_TYPE_EMS/DISCOVERY_TYPE_LC */
    int                islocal;           /* 1: EMS/LC device on the same device, 0: remote device */
    char               sn[32];            /* gateway SN */
    char               ipaddr[20];        /* ip address */
    char               softver[20];       /* software version string */
    int                 fire;            /* 1: fire, 0: normal */
} disc_devinfo;

/* macro-definitions for `dmi_type: */
#define DISCOVERY_MSGTYPE_NONE            0x0
#define DISCOVERY_MSGTYPE_BASIC           0x2401
#define DISCOVERY_MSGTYPE_SETIPADDR       0x2402
#define DISCOVERY_MSGTYPE_REBOOT          0x2403

typedef struct discmsg_basic_t {
    char               ipaddr[20];
    char               softver[20];
    // v1.48.200版本以后添加:fire
    int                fire;
} discmsg_basic;

// load from JSON configuration file
struct hash_intptr * load_discovery_config(int * numdevs);

// free pointer returned by `load_discovery_config
void free_discovery_config(struct hash_intptr * pdevs);

// format configured list of devices as JSON buffer
int get_discover_cfgbuf(struct hash_intptr * pdevs, int num,
    char * output, int maxlen);

// 返回数量可能包含自己（使能LC），返回可能为0
int lc_get_discover_dev_num();

// return discovered list of clients
disc_devinfo * get_discover_devs(int * numdevs);

// format discovered a list of gateway as JSON buffer
int get_discover_devbuf(disc_devinfo * gws, int num,
    char * output, int maxlen);

// free pointer returned by `get_discover_devs()
void free_discover_devs(disc_devinfo * gws, int num);

/*
 * initialize discovery working thread.
 *
 * `emstype should be DISCOVERY_TYPE_EMS/DISCOVERY_TYPE_LC
 */
int lc_discover_init(const char * sn, unsigned int emstype, int en_lo_lc);

// Structure definition for `DISCOVERY_MSGTYPE_SETIPADDR
// After discussion, netmask fixed to 255.255.255.0
typedef struct discmsg_setip_t {
    char               sn[32];
    char               gwip[20];
    char               ipaddr[20];
} discmsg_setip;

// set the IP address for LC, only called by EMS
int set_discovery_ipaddr(const char * sn,
    const char * ipaddr, const char * gwip);

#define DISCMSG_REBOOT_MAGIC              0x20240725
// Structure definition for `DISCOVERY_MSGTYPE_REBOOT
typedef struct discmsg_reboot_t {
    unsigned int       reboot_magic;
    char               sn[32];
    unsigned char      sys_reboot;
    unsigned char      app_reboot;
} discmsg_reboot;

// instruct broadcast peer to reboot
int set_discovery_reboot(const char * sn, int sysreboot, int appreboot);

int discovery_device_reboot(const char * devno, int sysreboot, int appreboot);

// restart emu_lc for LC, only called by EMS, via OPC-UA
int discovery_device_cmd(const char * devno,
    const char * command, char * * reply);

#endif
