#ifndef LIBACP_LIBACPDEF_H_
#define LIBACP_LIBACPDEF_H_

#include <stdint.h>

#ifndef IN
#define IN
#endif

#ifndef OUT
#define OUT
#endif

#define CONN_TYPE_TCP 0         // TCP通讯
#define CONN_TYPE_UDP 1         // UDP通讯
#define CONN_TYPE_LINUXSHM 2    // Linux使用共享内存通讯
#define CONN_TYPE_WINSHM 3      // 双域下的共享内存
#define CONN_TYPE_UNIXDOMAIN 4  // domain的socket的域

#define MIN_ROUTER_PORT 1      // 最小路由端口
#define MAX_ROUTER_PORT 65535  // 最大路由端口

// ACP PORT 1~300之间为ACP系统服务保留的路由port
#define ACPPORT_R0_ECHO 100
#define ACPPORT_R0_PLC_DEV 101
#define ACPPORT_R0_CMP_REGISTER 102    // 组件注册的port
#define ACPPORT_R0_PUBSUB 103          // 发布订阅系统
#define ACPORT_R0_CMP_MSG_FROWARD 104  // 组件消息转发的port
#define ACPORT_R0_FILE_SYSTEM 200      // 文件系统的操作

// ACP Id group
#define ACPIGRP_SYM_PLCDEVICE 0x1000  // read PLC parameter
#define ACPIGRP_SYM_PLCPSTATUS 0x2000
#define ACPIGRP_SYS_FILESYSTEM 0x3000
// ACP Id offset

#define ACPIOFFS_READ_DEVICEID 0x1001        // 读deviceId
#define ACPIOFFS_WRITE_DEVICEID 0x1002       // 写deviceId
#define ACPIOFFS_UPLOAD_SERIALNUMBER 0x1003  // 上传设备的序列号
#define ACPIOFFS_FILE_DOWNLOAD 0x3001

typedef void* ACP_HANDER;
typedef void* ACPCONN_HANDLE;  // 路由回调的通讯句柄
typedef void* msg_connection;

#pragma pack(push, 1)
typedef struct _AcpVersion {
  /** Version number. */
  uint8_t version;
  /** Revision number. */
  uint8_t revision;
  /** patch number */
  uint16_t patch;
} AcpVersion, *pAcpVersion;

typedef struct _AcpDeviceId {
  uint8_t b[6];
} AcpDeviceId, *pAcpDeviceId;

typedef struct _AcpDeviceAddr {
  /** Acp device Id */
  AcpDeviceId deviceId;
  /** Local Port */
  uint16_t port;
} AcpDeviceAddr, *pAcpDeviceAddr;

typedef struct _AcpDevice {
  char szDeviceIp[32];       // 设备的IP地址
  char szProdType[32];       // 设备的产品类型 sx5 sx2
  char szMacAddr[32];        // 设备的mac地址
  char szSerailNumber[32];   // codesys的序列号
  char szSn[32];             // 设备的sn号
  char szAcpDeviceId[32];    // 设备Acp的DeviceId
  char szAcpVersion[32];     // 设备ACP的服务Version
  char szRteVersion[32];     // 机器RTE的版本
  char szMetaOsVersion[32];  // Meta Os的Version
  char szHostName[32];       //  主机名称
} AcpDevice, *pAcpDevice;

typedef struct _AcpClientConfig {
  uint32_t timeoutMs;
} AcpClientConfig;

typedef struct _msg_request {
  const uint8_t nStatusFlag;  // StatusFlag
  const uint16_t nCmdId;      // CmdId read/write/read_write
  const uint32_t nInvokeId;   // message Id
  const uint32_t nIdGroup;    // index group in ACP server interface
  const uint32_t nIdOffset;   // index offset in ACP server interface
  uint32_t nErrorId;          // response error Id
  const msg_connection msg_conn;
} msg_request;

#pragma pack(pop)

/*
 *@breif:设置发现的回调函数
 *@param: acpDevice   扫描到服务端的DeviceId
 *@param: data           数据缓冲区起始地址
 *@param: len            数据缓冲区大小
 *@param: lpContext      用户指针
 */
typedef void (*pfnAcpDeviceScanCallback)(AcpDevice acpDevice, void* lpConetext);

/*
 *@breif:客户端与服务端连接和断开连接的回调函数
 *@param: acpDeviceId   要连接的deviceId
 *@param: lpContext     设置连接回调的是用户指针数据
 *@param: rc            连接回调的状态
 */
typedef void (*pfnAcpConnCallback)(AcpDeviceId* acpDeviceId, void* lpContext, int rc);

/*
 *@breif:服务端注册路由事件回调函数
 *@param: data      数据缓冲区起始地址
 *@param: dataLen   数据缓冲区大小
 *@param: port      路由的port
 *@param: req       接收到客户端的一次消息的请求
 *@param: lpContext 添加路由的时候用户指针
 */
typedef void (*pfnServerMsgRouterCallBack)(uint16_t port, const char* data, uint32_t len, msg_request req,
                                           void* lpContext);

/*
 *@breif:客户端注册路由事件回调函数
 *@param: data      数据缓冲区起始地址
 *@param: dataLen   数据缓冲区大小
 *@param: port      路由的port
 *@param: lpContext 添加路由的时候用户指针
 */
typedef void (*pfnClientMsgRouterCallBack)(uint16_t port, const char* data, uint32_t len, void* lpContext);

/*
 *@breif:发布订阅回调函数
 *@param: szTopic 订阅的topic
 *@param: data    topic订阅到的数据缓冲区起始地址
 *@param: dataLen topic订阅到的数据缓冲区大小
 *@param: lpContext 订阅的时候传入的用户指针数据
 */
typedef void (*pfnSubscribeCallback)(const char* szTopic, const char* data, uint32_t dataLen, void* lpContext);

/*
@breif: 服务端或者组件服务的,有新客户端连接的回调函数
*@param: conn 新客户端的连接句柄
*@param: lpContext  回调通知的用户指针
*/
typedef void (*pfnOnClientConnect)(ACPCONN_HANDLE conn, void* lpContext);

/*
@breif:客户端断开连接的回调函数
*@param: conn 断开连接的客户端的连接句柄
*@param: lpContext  回调通知的用户指针
*/
typedef void (*pfnOnClientDisConnect)(ACPCONN_HANDLE conn, void* lpContext);

/**
 * @brief 文件传输进度的回调函数
 * @param in: deviceId    连接的ACP服务的deviceId
 * @param in: nTransferId  AcpFileTransfer函数返回的transferId
 * @param in: progress    当前上传或者下载文件的进度
 * @param in: err         错误码信息,是否出错
 * @param in: status      等待0、传输中1、传输完成2、传输出错3
 * @param in: lpContext   传入回调的用户参数
 * @return out: 返回-1 表示中断传输, 返回0 表示正常
 */
typedef int (*pfnFileTransferCallback)(AcpDeviceId deviceId, int nTransferId, float progress, int err, int status,
                                       void* lpContext);

/**
 * @brief 接收ACP服务的控制消息(预留,暂未实现)
 * @param in: nCmd        控制命令码
 * @param in: data        控制消息数据缓冲区
 * @param in: dataLen     控制消息的缓冲区长度
 * @param in: lpContext   注册回调函数的用户指针用户指针
 * @return : 回调函数成功接收ACP服务命令
 *           返回0
 *           否则返回-1
 */
typedef int (*pfnOnControlCallback)(uint32_t nCmd, const char* data, uint32_t dataLen, void* lpContext);

typedef int (*pfnAcpReadCallback)(AcpDeviceAddr* pServerAddr, void* lpContext, uint32_t requestId, uint32_t status,
                                  void* data, uint32_t dataLen);

typedef int (*pfnAcpWriteCallback)(AcpDeviceAddr* pServerAddr, void* lpContext, uint32_t requestId, uint32_t status);

#endif  // LIBACP_LIBACPDEF_H_
