/**
 * @file    myComm.h
 * @brief   通讯抽象层 — 纯 C 接口
 * @details 提供 TCP/UDP/UART 统一通讯抽象，支持：
 *          - TCP 服务器/客户端
 *          - UDP 服务器/客户端
 *          - UART 串口通讯
 *          - 异步接收回调 + 状态变化回调
 *          - 基于 epoll 的单线程事件循环
 */
#ifndef _MY_COMM_H_
#define _MY_COMM_H_

#include "myBase.h"

#ifdef __cplusplus
extern "C"
{
#endif

/* === 通讯类型枚举 === */
typedef enum
{
    COMM_TYPE_TCP_SERVER = 0,   /** TCP 服务器（监听+accept） */
    COMM_TYPE_TCP_CLIENT,       /** TCP 客户端 */
    COMM_TYPE_UDP_SERVER,       /** UDP 服务器 */
    COMM_TYPE_UDP_CLIENT,       /** UDP 客户端 */
    COMM_TYPE_UART              /** UART 串口 */
} enum_comm_type;

/* === 通讯状态枚举 === */
typedef enum
{
    COMM_STATE_DISCONNECTED = 0, /** 未连接 */
    COMM_STATE_CONNECTING,       /** 连接中 */
    COMM_STATE_CONNECTED,        /** 已连接 */
    COMM_STATE_ERROR             /** 错误状态 */
} enum_comm_state;

/* === 错误码 === */
#define COMM_OK              0    /** 成功 */
#define COMM_ERR_PARAM      -1    /** 参数错误 */
#define COMM_ERR_MEM         -2    /** 内存不足 */
#define COMM_ERR_SOCKET      -3    /** Socket 创建失败 */
#define COMM_ERR_BIND        -4    /** 绑定失败 */
#define COMM_ERR_LISTEN      -5    /** 监听失败 */
#define COMM_ERR_CONNECT     -6    /** 连接失败 */
#define COMM_ERR_SEND        -7    /** 发送失败 */
#define COMM_ERR_NOT_FOUND   -8    /** 实例不存在 */
#define COMM_ERR_STATE       -9    /** 状态错误 */
#define COMM_ERR_INTERNAL   -10    /** 内部错误 */

/* === 通讯参数结构体 === */

/** TCP 参数 */
typedef struct
{
    char local_ip[64];       /** 本地 IP（服务器用） */
    int  local_port;         /** 本地端口（服务器用） */
    char remote_ip[64];      /** 远端 IP（客户端用） */
    int  remote_port;        /** 远端端口（客户端用） */
} stru_tcp_para;

/** UDP 参数 */
typedef struct
{
    char local_ip[64];       /** 本地 IP */
    int  local_port;         /** 本地端口 */
    char remote_ip[64];      /** 远端 IP（客户端用） */
    int  remote_port;        /** 远端端口（客户端用） */
} stru_udp_para;

/** UART 参数 */
typedef struct
{
    char device[128];        /** 串口设备路径（如 /dev/ttyS0） */
    int  baudrate;           /** 波特率 */
    int  data_bits;          /** 数据位（5/6/7/8） */
    int  stop_bits;          /** 停止位（1/2） */
    char parity;             /** 校验位（'N'/'E'/'O'） */
} stru_uart_para;

/** 通讯参数联合体 */
typedef union
{
    stru_tcp_para  tcp;
    stru_udp_para  udp;
    stru_uart_para uart;
} union_comm_para;

/* === 回调函数类型 === */

/**
 * @brief 接收数据回调
 * @param id   实例 ID
 * @param fd   接收数据的文件描述符
 * @param data 数据缓冲区
 * @param len  数据长度
 */
typedef void (*comm_recv_cb)(int id, int fd, const unsigned char *data, int len);

/**
 * @brief 状态变化回调
 * @param id    实例 ID
 * @param fd    文件描述符
 * @param state 新状态（enum_comm_state）
 */
typedef void (*comm_state_cb)(int id, int fd, int state);

/* === API 接口 === */

/**
 * @brief 创建通讯实例
 * @param type  通讯类型（enum_comm_type）
 * @param debug 调试模式（1=打印调试信息, 0=静默）
 * @param para  通讯参数指针
 * @return >=0 成功返回实例 ID, <0 失败返回错误码
 */
int comm_create(int type, int debug, const union_comm_para *para);

/**
 * @brief 建立连接
 * @details TCP 客户端发起 connect, TCP 服务器开始 listen,
 *          UDP 进行 bind, UART 打开串口。
 * @param id 实例 ID
 * @return COMM_OK 成功, <0 失败
 */
int comm_connect(int id);

/**
 * @brief 断开连接（不清除参数，可重新 comm_connect）
 * @param id 实例 ID
 * @return COMM_OK 成功, <0 失败
 */
int comm_disconnect(int id);

/**
 * @brief 发送数据
 * @param id   实例 ID
 * @param fd   目标 fd（TCP 服务器发送给指定客户端）
 * @param data 数据缓冲区
 * @param len  数据长度
 * @return >=0 实际发送字节数, <0 失败
 */
int comm_send(int id, int fd, const unsigned char *data, int len);

/**
 * @brief 注册接收数据回调
 * @param id 实例 ID
 * @param cb 回调函数指针
 * @return COMM_OK 成功, <0 失败
 */
int comm_recv_register(int id, comm_recv_cb cb);

/**
 * @brief 注册状态变化回调
 * @param id 实例 ID
 * @param cb 回调函数指针
 * @return COMM_OK 成功, <0 失败
 */
int comm_state_register(int id, comm_state_cb cb);

/**
 * @brief 销毁通讯实例并释放所有资源
 * @param id 实例 ID
 * @return COMM_OK 成功, <0 失败
 */
int comm_destroy(int id);

/**
 * @brief 启动通讯事件循环（阻塞调用，需在独立线程中调用）
 * @details 内部使用 epoll 监听所有已注册 fd，分发读/写/错误事件。
 *          该函数阻塞直到 comm_stop() 被调用。
 * @return COMM_OK 正常退出, <0 失败
 */
int comm_run(void);

/**
 * @brief 停止通讯事件循环
 */
void comm_stop(void);

#ifdef __cplusplus
}
#endif

#endif /* _MY_COMM_H_ */
