#ifndef __SOCK_MSG_H__
#define __SOCK_MSG_H__

#include <stdint.h>
#include <sys/socket.h>

// 读写模式宏定义
#define SOCK_READ 0x01
#define SOCK_WRITE 0x02

#define BUFFER_SIZE 4096 // 缓冲区大小
#define MAX_CLIENTS 10   // 最大连接客户端数量

/** 定义函数指针类型 */
typedef int (*sock_callback_t)(int, uint8_t *, int);

// 全局的消息队列
#define MAX_MESSAGES 10

// 消息类型
typedef struct
{
    uint16_t type;
    uint32_t code;
} Message;

typedef enum
{
    MSG_CAN_HEARTBEAT = 0x00,        // CAN心跳。使用msg_data_t结构,其中pad中填充msg_can_t数据
    MSG_CAN_OD = 0x01,               // CAN PDO变化。使用msg_data_t结构,其中pad中填充msg_can_t数据
    MSG_CAN_SDO_READ = 0x02,         // SDO读响应。使用msg_data_t结构,其中pad中填充msg_can_t数据
    MSG_CAN_SDO_WRITE = 0x03,        // SDO写响应。使用msg_data_t结构,其中pad中填充msg_can_t数据
    MSG_CPU_TEMP_ALARM = 0x04,       // CPU温度报警。使用msg_data_t结构,type为MSG_CPU_TEMP_ALARM,code为CPU温度(x1000)
    MSG_EEPROM_ERROR = 0x05,         // EEPROM异常。使用msg_data_t结构,type为MSG_EEPROM_ERROR,code为1
    MSG_KEY_PRESS = 0x06,            // 按键。使用msg_data_t结构,type为MSG_KEY_PRESS,code的低16位为按键值,code的高16位为状态(0:释放,1:按下)
    MSG_UPGRADE_STATE = 0x07,        // 升级状态。使用msg_data_t结构,type为MSG_UPGRADE_STATE
    MSG_CAN_HEARTBEAT_STATUS = 0x08, // CAN心跳状态变化。使用msg_data_t结构,其中pad中填充msg_can_t数据,var为nodid,val_int32为NMT状态(-1表示出错)
    MSG_UPGRADE_MESSAGE = 0x0a,
    MSG_UDISK_HOTPLUG = 0x0b,
    MSG_CAN_BUS1_OFF = 0x0c,
    MSG_CAN_BUS2_OFF = 0x0d,
    MSG_UPGRADE_DETAIL = 0x0f,        // CAN升级消息,使用msg_data_t结构,其中pad中填充msg_update_t数据
    MSG_BATTERY_CHARGE_ENABLE = 0x20, // 电池充电开关状态变化
    MSG_BATTERY_TEMP_ALARM = 0x21,    // 电池温度报警
    MSG_SYS_SUSPEND = 0x30,           // 系统挂起
    MSG_SYS_RESUME = 0x31,            // 系统挂起后唤醒
    MSG_SYS_POWEROFF = 0x32,          // 系统关机
    MSG_GPS_INFO = 0x40,              // GPS定位信息(gps_info_t)
    MSG_MCU_ERROR = 0x50,             // 与MCU通信失败
    MSG_ALERT_INFO = 0X80,            // 关键日志消息
} msg_type_t;

typedef enum
{
    MSG_CHAN_APP = 0, // GUI程序
    MSG_CHAN_LIM,     // 力限器程序
    MSG_CHAN_IOMOD,   // IO模块
    MSG_CHAN_MAX,     // 最大通道数
    MSG_CHAN_UNKNOWN, // 未知通道
} msg_channel_t;

typedef struct
{
    msg_type_t type;
    uint32_t code;
    int len;
    char pad[BUFFER_SIZE];
} msg_data_t;

extern int msgid;

/**
 * @brief	初始化一个网络通讯用的socket句柄
 *
 * @param	server: 是否为server模式
 * @param   ipaddr: server模式的绑定IP地址
 * @param   port: server模式的绑定端口
 * @retval	>=0: socket句柄;否则失败
 */
int sock_init(int server, uint32_t ipaddr, uint32_t port);

/**
 * @brief	销毁socket句柄
 *
 * @param	fd: socket句柄
 * @retval	无
 */
void sock_exit(int fd);

/**
 * @brief socket发送数据
 *
 * @param fd: socket句柄
 * @param buf: 待发送数据
 * @param len: 待发送数据长度
 * @retval >=0: 成功发送的字节数,否则失败
 */
int sock_write(int fd, const uint8_t *buf, int len);

/**
 * @brief socket接收数据
 *
 * @param fd: socket句柄
 * @param buf: 数据接收缓存
 * @param len: 数据接收缓存长度
 * @retval >0: 成功读取长度,否则读取失败
 */
int sock_read(int fd, uint8_t *buf, int len);

/**
 * @brief 获取socket连接端点地址信息
 *
 * @param fd: socket句柄
 * @param ipaddr: 获取远端IP地址
 * @param port: 获取远端的端口
 * @retval 0: 成功,否则失败
 */
int sock_info(int fd, uint32_t *ipaddr, uint32_t *port);

/**
 * @brief 注册socket读写监听。当有读写操作时,会调用相应的回调函数cb
 *
 * @param fd: socket句柄
 * @param cb: socket事件回调函数
 * @param mode: SOCK_READ: 监听读,SOCK_WRITE: 监听写
 * @retval 0: 成功,否则失败
 */
int sock_ev_register(int fd, sock_callback_t cb, uint32_t mode);

/**
 * @brief	注销socket读写监听
 *
 * @param	fd: socket句柄
 * @retval	0: 成功,<0: 失败
 */
int sock_ev_unregister(int fd);

int init_msg_queue();

int destroy_msg_queue();

/**
 * @brief 接收本地消息,主要用于进程间消息通讯
 *
 * @param msg: 消息类型&数据
 * @retval >0接收数据字节数;<=0: 失败
 */
int msg_local_recv(msg_data_t *msg);

/**
 * @brief	发送本地消息,主要用于进程间消息通讯
 *
 * @param type: 消息类型,如下:
    enum msg_type_t
    {
        MSG_CAN_HEARTBEAT = 0x00,	  // CAN心跳。使用msg_data_t结构,其中pad中填充msg_can_t数据
        MSG_CAN_OD = 0x01,		  // CAN PDO变化。使用msg_data_t结构,其中pad中填充msg_can_t数据
        MSG_CAN_SDO_READ = 0x02,  // SDO读响应。使用msg_data_t结构,其中pad中填充msg_can_t数据
        MSG_CAN_SDO_WRITE = 0x03, // SDO写响应。使用msg_data_t结构,其中pad中填充msg_can_t数据

        MSG_CPU_TEMP_ALARM = 0x04, // CPU温度报警。使用msg_data_t结构,type为MSG_CPU_TEMP_ALARM,code为CPU温度(x1000)
        MSG_EEPROM_ERROR = 0x05,   // EEPROM异常。使用msg_data_t结构,type为MSG_EEPROM_ERROR,code为1
        MSG_KEY_PRESS = 0x06,	   // 按键。使用msg_data_t结构,type为MSG_KEY_PRESS,code的低16位为按键值,code的高16位为状态(0:释放,1:按下)
        MSG_UPGRADE_STATE = 0x07,  // 升级状态。使用msg_data_t结构,type为MSG_UPGRADE_STATE

        MSG_CAN_HEARTBEAT_STATUS = 0x08, // CAN心跳状态变化。使用msg_data_t结构,其中pad中填充msg_can_t数据,var为nodid,val_int32为NMT状态(-1表示出错)
        MSG_UPGRADE_MESSAGE = 0x0a,
        MSG_UDISK_HOTPLUG = 0x0b,
        MSG_CAN_BUS1_OFF = 0x0c,
        MSG_CAN_BUS2_OFF = 0x0d,
        MSG_UPGRADE_DETAIL = 0x0f, // CAN升级消息,使用msg_data_t结构,其中pad中填充msg_update_t数据

        MSG_BATTERY_CHARGE_ENABLE = 0x20, // 电池充电开关状态变化
        MSG_BATTERY_TEMP_ALARM = 0x21,	  // 电池温度报警

        MSG_SYS_SUSPEND = 0x30,	 // 系统挂起
        MSG_SYS_RESUME = 0x31,	 // 系统挂起后唤醒
        MSG_SYS_POWEROFF = 0x32, // 系统关机

        MSG_GPS_INFO = 0x40,   // GPS定位信息(gps_info_t)
        MSG_MCU_ERROR = 0x50,  // 与MCU通信失败
        MSG_ALERT_INFO = 0X80, // 关键日志消息
    };
 * @param code : 消息代码
 * @param pad : 附件消息内容
 * @param len : 附件消息长度
 * @retval	0: 成功 <0: 失败
 */
int msg_local_send(uint16_t type, uint32_t code, void *pad, int len);

/**
 * @brief	本地进程间发送信号(整形)
 *
 * @param type: 消息类型
 * @param code: 消息代码
 * @retval	0: 成功<0: 失败
 */
int msg_local_send_pulse(uint16_t type, uint32_t code);

/**
 * @brief	接收消息,主要用于进程间消息通讯
 *
 * @param channel: 消息通道
 *    enum msg_channel_t
 *    {
 *        MSG_CHAN_APP     = 0,      // GUI程序
 *        MSG_CHAN_LIM,             // 力限器程序
 *        MSG_CHAN_IOMOD,             // IO模块
 *        MSG_CHAN_MAX,              // 最大通道数
 *        MSG_CHAN_UNKNOWN,             //
 *    };
 * @param   msg: 消息类型&数据
 * @retval	>0接收数据字节数;<=0: 失败
 */
int msg_recv(int channel, msg_data_t *msg);

/**
 * @brief	发送消息,主要用于进程间消息通讯
 *
 * @param channel: 消息通道
 *    enum msg_channel_t {
 *            MSG_CHAN_APP     = 0,      // GUI程序
 *            MSG_CHAN_LIM,             // 力限器程序
 *            MSG_CHAN_IOMOD,             // IO模块
 *            MSG_CHAN_MAX,              // 最大通道数
 *            MSG_CHAN_UNKNOWN,             //
 *    };
 * @param type: 消息类型,如下:
 *    enum msg_type_t
 *    {
 *        MSG_CAN_HEARTBEAT = 0x00,	  // CAN心跳。使用msg_data_t结构,其中pad中填充msg_can_t数据
 *        MSG_CAN_OD = 0x01,		  // CAN PDO变化。使用msg_data_t结构,其中pad中填充msg_can_t数据
 *        MSG_CAN_SDO_READ = 0x02,  // SDO读响应。使用msg_data_t结构,其中pad中填充msg_can_t数据
 *        MSG_CAN_SDO_WRITE = 0x03, // SDO写响应。使用msg_data_t结构,其中pad中填充msg_can_t数据
 *
 *        MSG_CPU_TEMP_ALARM = 0x04, // CPU温度报警。使用msg_data_t结构,type为MSG_CPU_TEMP_ALARM,code为CPU温度(x1000)
 *        MSG_EEPROM_ERROR = 0x05,   // EEPROM异常。使用msg_data_t结构,type为MSG_EEPROM_ERROR,code为1
 *        MSG_KEY_PRESS = 0x06,	   // 按键。使用msg_data_t结构,type为MSG_KEY_PRESS,code的低16位为按键值,code的高16位为状态(0:释放,1:按下)
 *        MSG_UPGRADE_STATE = 0x07,  // 升级状态。使用msg_data_t结构,type为MSG_UPGRADE_STATE
 *
 *        MSG_CAN_HEARTBEAT_STATUS = 0x08, // CAN心跳状态变化。使用msg_data_t结构,其中pad中填充msg_can_t数据,var为nodid,val_int32为NMT状态(-1表示出错)
 *        MSG_UPGRADE_MESSAGE = 0x0a,
 *        MSG_UDISK_HOTPLUG = 0x0b,
 *        MSG_CAN_BUS1_OFF = 0x0c,
 *        MSG_CAN_BUS2_OFF = 0x0d,
 *        MSG_UPGRADE_DETAIL = 0x0f, // CAN升级消息,使用msg_data_t结构,其中pad中填充msg_update_t数据
 *
 *        MSG_BATTERY_CHARGE_ENABLE = 0x20, // 电池充电开关状态变化
 *        MSG_BATTERY_TEMP_ALARM = 0x21,	  // 电池温度报警
 *
 *        MSG_SYS_SUSPEND = 0x30,	 // 系统挂起
 *        MSG_SYS_RESUME = 0x31,	 // 系统挂起后唤醒
 *        MSG_SYS_POWEROFF = 0x32, // 系统关机
 *
 *        MSG_GPS_INFO = 0x40,   // GPS定位信息(gps_info_t)
 *        MSG_MCU_ERROR = 0x50,  // 与MCU通信失败
 *        MSG_ALERT_INFO = 0X80, // 关键日志消息
 *    };
 * @param    code : 消息代码
 * @param    pad : 附件消息内容
 * @param    len : 附件消息长度
 * @retval	0: 成功<0: 失败
 */
int msg_send(int channel, uint16_t type, uint32_t code, void *pad, int len);
#endif /** __SOCK_MSG_H__ */