#ifndef AGVC_INTERFACE_TYPE_H
#define AGVC_INTERFACE_TYPE_H

#include <string>
#include <vector>
#include <cstdint>

namespace agvc_interface {
/// 接口函数返回值定义
///
/// +数为警告，负数为错误，0为没有错误也没有警告
#define ENUM_AgvcErrorCodes_DECLARES                                       \
    ENUM_ITEM(AGVC_OK, 0, "成功")                                          \
    ENUM_ITEM(AGVC_BAD_STATE, 1, "状态错误")                               \
    ENUM_ITEM(AGVC_QUEUE_FULL, 2, "规划队列满")                            \
    ENUM_ITEM(AGVC_BUSY, 3, "上一条指令正在执行中")                        \
    ENUM_ITEM(AGVC_TIMEOUT, 4, "超时")                                     \
    ENUM_ITEM(AGVC_INVL_ARGUMENT, 5, "参数无效")                           \
    ENUM_ITEM(AGVC_NOT_IMPLETEMENT, 6, "接口未实现")                       \
    ENUM_ITEM(AGVC_NO_ACCESS, 7, "无法访问")                               \
    ENUM_ITEM(AGVC_CONN_REFUSED, 8, "连接被拒绝")                          \
    ENUM_ITEM(AGVC_CONN_RESET, 9, "连接被重置")                            \
    ENUM_ITEM(AGVC_INPROGRESS, 10, "正在执行中")                           \
    ENUM_ITEM(AGVC_EIO, 11, "input/output error")                          \
    ENUM_ITEM(AGVC_NOBUFFS, 12, "")                                        \
    ENUM_ITEM(AGVC_REQUEST_IGNORE, 13, "本次请求被忽略")                   \
    ENUM_ITEM(AGVC_ALGORITHM_PLAN_FAILED, 14, "运动规划算法错误")          \
    ENUM_ITEM(AGVC_VERSION_INCOMPAT, 15, "接口版本不匹配")                 \
    ENUM_ITEM(AGVC_DIMENSION_ERR, 16, "输入参数维数不对")                  \
    ENUM_ITEM(AGVC_SINGULAR_ERR, 17, "输入的配置可能会奇异")               \
    ENUM_ITEM(AGVC_POS_BOUND_ERR, 18, "输入的位置边界超过极限范围")        \
    ENUM_ITEM(AGVC_INIT_POS_ERR, 19, "初始位置输入不合理")                 \
    ENUM_ITEM(AGVC_ELP_SETTING_ERR, 20, "包络体设置错误")                  \
    ENUM_ITEM(AGVC_TRAJ_GEN_FAIL, 21, "轨迹生成失败")                      \
    ENUM_ITEM(AGVC_TRAJ_SELF_COLLISION, 22, "轨迹自碰撞")                  \
    ENUM_ITEM(AGVC_IK_NO_CONVERGE, 23, "逆解计算不收敛，计算出错")         \
    ENUM_ITEM(AGVC_IK_OUT_OF_RANGE, 24, "逆解计算超出机器人最大限制")      \
    ENUM_ITEM(AGVC_IK_CONFIG_DISMATCH, 25, "逆解输入配置存在错误")         \
    ENUM_ITEM(AGVC_IK_JACOBIAN_FAILED, 26, "逆解雅可比矩阵计算失败")       \
    ENUM_ITEM(AGVC_IK_NO_SOLU, 27, "目标点存在解析解，但均不满足选解条件") \
    ENUM_ITEM(AGVC_IK_UNKOWN_ERROR, 28, "逆解返回未知类型错误")            \
    ENUM_ITEM(AGVC_ERR_UNKOWN, 99999, "Unkown error occurred.")            \
    ENUM_ITEM(STATION_SRV_OK, 100, "站点操作成功")                         \
    ENUM_ITEM(STATION_SRV_NOT_FOUND, -101, "站点服务器未响应")             \
    ENUM_ITEM(STATION_CREAT_FAILED, -102, "站点创建失败")                  \
    ENUM_ITEM(STATION_DELETE_FAILED, -103, "站点删除失败")                 \
    ENUM_ITEM(PATH_SRV_OK, 200, "路径操作成功")                            \
    ENUM_ITEM(PATH_SRV_NOT_FOUND, -201, "路径服务器未响应")                \
    ENUM_ITEM(PATH_CREAT_FAILED, -202, "路径创建失败")                     \
    ENUM_ITEM(PATH_DELETE_FAILED, -203, "路径删除失败")                    \
    ENUM_ITEM(MAP_SRV_OK, 300, "地图操作成功")                             \
    ENUM_ITEM(MAP_SRV_NOT_FOUND, -301, "地图服务器未响应")                 \
    ENUM_ITEM(MAP_HEADER_LIST_FAILED, -302, "获取地图header list 失败")    \
    ENUM_ITEM(MAP_HEADER_FAILED, -303, "获取地图header失败")               \
    ENUM_ITEM(MAP_SET_FAILED, -304, "地图设置失败")                        \
    ENUM_ITEM(MAP_SAVE_FAILED, -305, "地图保存失败")                       \
    ENUM_ITEM(MAP_SWITCH_FAILED, -306, "地图切换失败")                     \
    ENUM_ITEM(MAP_DELETE_FAILED, -307, "地图删除失败")                     \
    ENUM_ITEM(MAP_VIRTUAL_SRV_OK, 301, "虚拟区操作成功")                   \
    ENUM_ITEM(MAP_VIRTUAL_SRV_NOT_FOUND, -308, "虚拟区服务器未响应")       \
    ENUM_ITEM(MAP_VIRTUAL_SET_PARAM_WRONG, -309, "虚拟区设置参数错误")     \
    ENUM_ITEM(MAP_VIRTUAL_ADD_FAILED, -310, "添加虚拟区失败")              \
    ENUM_ITEM(MAP_VIRTUAL_DELETE_FAILED, -311, "删除虚拟区失败")           \
    ENUM_ITEM(IP_SRV_OK, 400, "IP操作成功")                                \
    ENUM_ITEM(IP_SRV_NOT_FOUND, -401, "ip设置服务器未响应")                \
    ENUM_ITEM(IP_NETWORK_NULL, -402, "ip地址网卡名称为空")                 \
    ENUM_ITEM(IP_ADDRESS_NULL, -403, "ip地址为空")                         \
    ENUM_ITEM(IP_SET_FAILED, -404, "ip设置失败")

#define ENUM_ITEM(c, n, ...) c = n,
enum AgvcErrorCodes : int
{
    ENUM_AgvcErrorCodes_DECLARES
};

/**
 * agv 运行模式
 */
enum class RunningMode
{
    NONE     = 0,
    START    = 1, ///< 开始模式
    MAPPING  = 2, ///< 建图模式
    NAVIGATE = 3, ///< 导航模式
    CHARGING = 4, ///< 自动充电模式
    MAINTAIN = 5, ///< 维护模式
    STOP     = 6, ///< 停止模式
};

/**
 * 路径的形状
 */
enum class PathShape
{
    NONE   = 0,
    LINE   = 1, ///< 直线
    ARC    = 2, ///< 圆弧
    BEZIER = 3, ///< 贝塞尔曲线
                ///< B_SPLINE = 4  // B样条曲线
};

/**
 * 地图格式
 */
enum class MapFormat
{
    NONE           = 0,
    OCCUPANCY_GRID = 1, ///< 占用栅格地图
    BASE64_PNG     = 2, ///< base64编码的png地图
};

/**
 * 地图中虚拟区域的类型
 */
enum class MapVirtualAreaType
{
    NONE      = 0,
    OBSTACLE  = 1, ///< 虚拟墙
    SLOW_DOWN = 2, ///< 减速区
    INFLATE   = 3, ///< 膨胀区
};

/**
 * 地图中虚拟区域的形状
 */
enum class MapVirtualAreaShape
{
    NONE    = 0,
    LINE    = 1, ///< 直线
    ARC     = 2, ///< 圆弧
    CIRCLE  = 3, ///< 圆形
    POLYGON = 4, ///< 多边形
};

/**
 * agv 导航类型
 */
enum class NavType
{
    NONE            = 0, ///< 空
    FREE_TO_POSE    = 1, ///< 自由导航到任意点
    FREE_TO_STATION = 2, ///< 自由导航到站点
    PATH_TO_STATION = 3, ///< 路径导航到站点
};

/**
 * @brief 自动充电类型
 * @since 0.7.0
 * @note 高电量阈值与低电量阈值在对外配置参数中进行修改
 */
enum class AutoChargingType
{
    NONE                   = 0, ///< 空
    LOW_POWER_TO_BOARD     = 1, ///< 低电量自动上桩； 如果当前电量低于低电量阈值，开始上桩；否则，不执行上桩；
    HIGH_POWER_LEAVE_BOARD = 2, ///< 高电量自动下桩； 如果当前电量高于高电量阈值，开始下桩；否则，不执行下桩；
    FORCE_TO_BOARD         = 3, ///< 强制自动上桩； 无视当前电量
    FORCE_LEAVE_BOARD      = 4, ///< 强制自动下桩； 无视当前电量
};

/**
 * 一个操作执行后反馈的状态
 */
enum class FeedbackStatus
{
    NONE     = 0, ///< 空
    FINISHED = 1, ///< 成功
    FAILED   = 2, ///< 失败
    RUNNING  = 3, ///< 正在运行
    PAUSED   = 4, ///< 暂停
    CANCELED = 5, ///< 取消
};

/**
 * 模块固件更新配置
 */
enum class FirmwareUpdateMode
{
    NONE          = 0, ///< 空 默认不更新固件
    UPDATE        = 1, ///< 更新固件
    FORCED_UPDATE = 2, ///< 强制更新固件
    NOT_UPDATE    = 3, ///< 不更新固件
};

// 脚本状态
enum class ScriptRuntimeState
{
    RUNNING  = 0, // 正在运行中
    PAUSED   = 1, // 暂停
    STOPPED  = 2, // 已停止
    ABORTING = 3, // 中止
};

/**
 * 标定类型
 */
enum class CalibrationType
{
    NONE       = 0, ///< 空
    LASER_ODOM = 1, ///< 激光-码盘里程计标定
};

/**
 * @brief agv 导航状态
 * @details
 * NONE     = 0, // 空\n
 * FINISHED = 1, // 向站点导航完成\n
 * FAILED   = 2, // 向站点导航失败\n
 * RUNNING  = 3, // 正在向站点导航\n
 * PAUSED   = 4, // 向站点导航暂停\n
 * CANCELED = 5, // 向站点导航取消
 */
typedef FeedbackStatus NavStatus;

/**
 * @brief 保存地图异步接口状态，调用接口 saveMap 后的状态
 * @details
 * NONE     = 0, // 保存地图接口未执行\n
 * FINISHED = 1, // 保存地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 保存地图中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SaveMapStatus;

/**
 * @brief 切换地图异步接口状态，调用接口 switchMap 后的状态
 * @details
 * NONE     = 0, // 切换地图接口未执行\n
 * FINISHED = 1, // 切换地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 切换地图中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SwitchMapStatus;

/**
 * @brief 切换运行模式异步接口状态，调用接口 changeRunningMode 后的状态
 * @details
 * NONE     = 0, // 切换运行模式接口未执行\n
 * FINISHED = 1, // 切换运行模式接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 切换运行模式中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus ChangeRunningModeStatus;

/**
 * @brief 重定位状态，调用接口 relocation 后的状态
 * @details
 * NONE     = 0, // 重定位接口未执行\n
 * FINISHED = 1, // 重定位接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 重定位中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus RelocationStatus;

/**
 * @brief 上传Png地图全部信息接口状态，调用接口 setPngMapAllInfo 后的状态
 * @details
 * NONE     = 0, // 设置地图信息接口未执行\n
 * FINISHED = 1, // 设置地图信息接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 地图信息上传中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SetPngMapAllInfoStatus;

/**
 * @brief 获取Png地图全部信息接口状态，调用接口 getPngMapAllInfo 后的状态
 * @details
 * NONE     = 0, // 获取地图信息接口未执行\n
 * FINISHED = 1, // 获取地图信息接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 地图信息获取中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus GetPngMapAllInfoStatus;

/**
 * @brief 获取栅格地图接口状态，调用接口 getGridMapFromAgv 后的状态
 * @details
 * NONE     = 0, // 获取栅格地图接口未执行\n
 * FINISHED = 1, // 获取栅格地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 栅格地图获取中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus GetGridMapStatus;

/**
 * @brief 发送栅格地图接口状态，调用接口 sendGridMapToAgv 后的状态
 * @details
 * NONE     = 0, // 发送栅格地图接口未执行\n
 * FINISHED = 1, // 发送栅格地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 发送栅格地图中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SendGridMapStatus;

/**
 * @brief 获取png地图接口状态，调用接口 getBase64PngMapFromAgv 后的状态
 * @details
 * NONE     = 0, // 获取png地图接口未执行\n
 * FINISHED = 1, // 获取png地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 获取png地图中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus GetPngMapStatus;

/**
 * @brief 发送png地图接口状态，调用接口 sendBase64PngMapToAgv 后的状态
 * @details
 * NONE     = 0, // 发送png地图接口未执行\n
 * FINISHED = 1, // 发送png地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // png地图发送中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SendPngMapStatus;

/**
 * @brief 设置栅格地图全部信息接口状态，调用接口 setGridMapAllInfo 后的状态
 * @details
 * NONE     = 0, // 发送栅格地图全部信息接口未执行\n
 * FINISHED = 1, // 发送栅格地图全部信息接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 栅格地图发送中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus SetGridMapAllInfoStatus;

/**
 * @brief 获取栅格地图全部信息接口状态，调用接口 getGridMapAllInfo 后的状态
 * @details
 * NONE     = 0, // 获取栅格地图全部信息接口未执行\n
 * FINISHED = 1, // 获取栅格地图全部信息接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 栅格地图全部信息获取中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus GetGridMapAllInfoStatus;

/**
 * @brief 获取栅格地图全部信息接口状态，调用接口 previewPngMapFromAgv 后的状态
 * @details
 * NONE     = 0, // 预览地图接口未执行\n
 * FINISHED = 1, // 预览地图接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 预览地图接口获取中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus PreviewPngMapStatus;

/**
 * @brief 获取自动上轨接口状态，调用接口 autoAlignRailway 后的状态
 * @details
 * NONE     = 0, // 自动上轨接口未执行\n
 * FINISHED = 1, // 自动上轨接口执行完毕\n
 * FAILED   = 2, // 无效值\n
 * RUNNING  = 3, // 自动上轨接口执行中\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 无效值
 */
typedef FeedbackStatus AutoAlignRailwayStatus;

/**
 * @brief 标定状态
 * @details
 * NONE     = 0, // 空\n
 * FINISHED = 1, // 标定完成\n
 * FAILED   = 2, // 标定失败\n
 * RUNNING  = 3, // 正在采集数据\n
 * PAUSED   = 4, // 无效值\n
 * CANCELED = 5, // 取消标定
 */
typedef FeedbackStatus CalibrationStatus;

/**
 * 二维点
 */
struct Point2d
{
    float x; ///< 单位 m
    float y; ///< 单位 m
};

/**
 * 二维位姿
 */
struct Pose2d
{
    double x;   ///< 单位 m
    double y;   ///< 单位 m
    double yaw; ///< 单位 rad
};

/**
 * 速度
 */
struct Speed
{
    double v; ///< 单位 m/s
    double w; ///< 单位 rad/s
};

/**
 * 头部信息
 */
struct Header
{
    std::string id;      ///< uuid
    std::string name;    ///< 名称
    int64_t stamp;       ///< 时间戳，UTC时间(1970年01月01日00时00分00秒~至今)，单位：纳秒
    std::string map_id;  ///< 当前地图的id,形式为uuid：例如a5e7c6de-4463-443e-8b25-ccbfd6a27aee,
                         ///< 与地图文件名字相同
    int error_code = -1; ///< 错误码
};

/**
 * agv 信息
 */
struct AgvDetails
{
    std::string name;                  ///< agv的名称
    std::string version;               ///< 当前控制程序的版本号
    std::string MFD;                   ///< 生产日期
    std::string SN;                    ///< S/N 码
    int communication_version;         ///< bridge 版本信息
    int battery_version;               ///< 电池版本信息
    int loop_times;                    ///< 电池循环次数
    float surplus_capacity;            ///< 电池剩余容量
    int left_motor_firmware_version;   ///< 左电机固件版本
    int right_motor_firmware_version;  ///< 右电机固件版本
    int master_board_firmware_version; ///< 接口板固件版本信息
    int hardware_abstraction_version;  ///< 硬件抽象层版本信息
    int error_code_version;            ///< 错误码版本
    float max_speed;                   ///< agv允许运行的最大线速度
    float max_angular;                 ///< agv允许运行的最大角速度
};

/**
 * agv 运行信息
 */
struct RunningInfo
{
    Header header;               ///< agv的SN码，agv的名称，当前时间，地图的id
    RunningMode running_mode;    ///< agv当前运行模式
    Speed current_speed;         ///< 当前行驶速度 {v w}，单位{m/s rad/s}
    int8_t location_score;       ///< 当前定位评分，[0-100]
    double total_dist;           ///< 累计行驶里程，单位 m
    double current_dist;         ///< 本次累计行驶里程，单位 m
    double total_running_time;   ///< 累计运行时间，单位 s
    double current_running_time; ///< 本次运行时间，单位 s
    double battery_voltage;      ///< 电池电压，单位 V
    double battery_current;      ///< 电池电流，单位 A
    int8_t remaining_voltage;    ///< 剩余电量，百分比 % [0-100]
    int8_t battery_status;       ///< 电池状态，0-无,1-放电，2-充电，3-充满，4-急需充电
    int8_t safety_edge_status;   ///< 安全触边状态，0-无,1-左前侧碰撞，2-右前碰撞，3-左后碰撞，4-右后碰撞
    bool low_battery;            ///< 是否电量低
    bool pause;                  ///< 是否处于暂停状态
    bool emergency_stop;         ///< 是否处于急停状态
    bool blocked;                ///< 是否被障碍物遮挡
    bool localization_loss;      ///< 是否定位丢失
    bool fault_alarm;            ///< 故障报警（电机故障、传感器故障、电池故障）,具体故障信息可在日志中查看
    bool break_release_flag;     ///< 是否释放刹车，true 代表释放，false 代表未释放
};

/**
 * 接口saveMap的工作状态
 */
struct SaveMapWorkingStatus
{
    Header header;        ///< header.id 代表下发的saveMap指令id
    SaveMapStatus status; ///< 接口SaveMap的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口switchMap的工作状态
 */
struct SwitchMapWorkingStatus
{
    Header header;          ///< header.id 代表下发的switchMap指令id
    SwitchMapStatus status; ///< 接口switchMap的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口changeRunningMode的工作状态
 */
struct ChangeModeWorkingStatus
{
    Header header;                  ///< header.id 代表下发的changeRunningMode指令id
    ChangeRunningModeStatus status; ///< 接口changeRunningMode的运行状态
                                    ///< NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口Relocation的工作状态
 */
struct RelocationWorkingStatus
{
    Header header;           ///< header.id 代表下发的Relocation指令id
    RelocationStatus status; ///< 接口Relocation的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口setPngMapAllInfo的工作状态
 */
struct SetPngMapAllInfoWorkingStatus
{
    Header header;                 ///< header.id 代表下发的setPngMapAllInfo指令id
    SetPngMapAllInfoStatus status; ///< 接口setPngMapAllInfo的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口getPngMapAllInfo的工作状态
 */
struct GetPngMapAllInfoWorkingStatus
{
    Header header;                 ///< header.id 代表下发的getPngMapAllInfo指令id
    GetPngMapAllInfoStatus status; ///< 接口getPngMapAllInfo的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口getGridMapFromAgv的工作状态
 */
struct GetGridMapWorkingStatus
{
    Header header;           ///< header.id 代表下发的getGridMapFromAgv指令id
    GetGridMapStatus status; ///< 接口getGridMapFromAgv的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口sendGridMapToAgv的工作状态
 */
struct SendGridMapWorkingStatus
{
    Header header;            ///< header.id 代表下发的sendGridMapToAgv指令id
    SendGridMapStatus status; ///< 接口sendGridMapToAgv的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

struct GetPngMapWorkingStatus
{
    Header header;          ///< header.id 代表下发的getBase64PngMapFromAgv指令id
    GetPngMapStatus status; ///< 接口getBase64PngMapFromAgv的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口sendBase64PngMapToAgv的工作状态
 */
struct SendPngMapWorkingStatus
{
    Header header;           ///< header.id 代表下发的sendBase64PngMapToAgv指令id
    SendPngMapStatus status; ///< 接口sendBase64PngMapToAgv的运行状态，NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口setGridMapAllInfo的工作状态
 */
struct SetGridMapAllInfoWorkingStatus
{
    Header header;                  ///< header.id 代表下发的setGridMapAllInfo指令id
    SetGridMapAllInfoStatus status; ///< 接口setGridMapAllInfo的运行状态
                                    ///< NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口getGridMapAllInfo的工作状态
 */
struct GetGridMapAllInfoWorkingStatus
{
    Header header;                  ///< header.id 代表下发的getGridMapAllInfo指令id
    GetGridMapAllInfoStatus status; ///< 接口getGridMapAllInfo的运行状态
                                    ///< NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口previewPngMapFromAgv的工作状态
 */
struct PreviewPngMapWorkingStatus
{
    Header header;              ///< header.id 代表下发的previewPngMapFromAgv指令id
    PreviewPngMapStatus status; ///< 接口previewPngMapFromAgv的运行状态
                                ///< NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 接口autoAlignRailway的工作状态
 */
struct AutoAlignRailwayWorkingStatus
{
    Header header;                 ///< header.id 代表下发的autoAlignRailway指令id
    AutoAlignRailwayStatus status; ///< 接口autoAlignRailway的运行状态
                                   ///< NONE -接口未执行 RUNNING-执行中，FINISH-执行结束
};

/**
 * 异步接口运行状态
 * 暂时存在14个异步接口：saveMap, switchMap, changeRunningMode, relocation, sendBase64PngMapToAgv
 * getGridMapAllInfo, setGridMapAllInfo, sendGridMapToAgv, getGridMapFromAgv
 * getPngMapAllInfo, setPngMapAllInfo, getBase64PngMapFromAgv, previewPngMapFromAgv, autoAlignRailway
 */
struct AsyncInterfaceResultStatus
{
    Header header;                                      ///< agv的SN码，agv的名称，当前时间，地图的id
    SaveMapWorkingStatus save_map_status;               ///< 保存地图(saveMap)接口的执行状态
    SwitchMapWorkingStatus switch_map_status;           ///< 切换地图(switchMap)接口的执行状态
    ChangeModeWorkingStatus change_running_mode_status; ///< 切换运行模式(changeRunningMode)接口的执行状态
    RelocationWorkingStatus relocation_status;          ///< 重定位(relocation)接口的执行状态
    GetGridMapWorkingStatus get_grid_map_status;        ///< 获取栅格地图(getGridMapFromAgv)接口的执行状态
    SendGridMapWorkingStatus send_grid_map_status;      ///< 发送栅格地图(sendGridMapToAgv)接口的执行状态
    GetPngMapWorkingStatus get_png_map_status;          ///< 获取png地图(getBase64PngMapFromAgv)接口的执行状态
    SendPngMapWorkingStatus send_png_map_status;        ///< 发送png地图(sendBase64PngMapToAgv)接口的执行状态
    SetPngMapAllInfoWorkingStatus set_png_all_status;   ///< 设置png地图全部信息(setPngMapAllInfo)接口的执行状态
    GetPngMapAllInfoWorkingStatus get_png_all_status;   ///< 获取png地图全部信息(getPngMapAllInfo)接口的执行状态
    SetGridMapAllInfoWorkingStatus set_grid_all_status; ///< 设置栅格地图全部信息(setGridMapAllInfo)接口的执行状态
    GetGridMapAllInfoWorkingStatus get_grid_all_status; ///< 获取栅格地图全部信息(getGridMapAllInfo)接口的执行状态
    PreviewPngMapWorkingStatus preview_png_map_status;  ///< 预览png地图(previewPngMapFromAgv)接口的执行状态
    AutoAlignRailwayWorkingStatus align_railway_status; ///< 自动上轨(autoAlignRailway)接口的执行状态
};

/**
 * 站点
 */
struct StationMark
{
    Header header;    ///< 站点id，站点名称，当前时间，站点所在地图的id
    std::string type; ///< 普通站点是"ST",充电站点“CP”
    Pose2d pose;      ///< 站点位姿，{x(m) y(m) theta(rad)}
};

/**
 * 通过站点表示路径
 */
struct PathStation
{
    Header header;                       ///< 路径id，路径名称，当前时间，路径所在地图的id
    PathShape shape;                     ///< 路径的形状
    bool use_direction;                  ///< 生成站点时是否使用站点方向
    double max_speed;                    ///< agv经过该路径时的最大速度
    std::string start_station_id;        ///< 路径起点站点id
    std::string end_station_id;          ///< 路径终点站点id
    std::vector<Point2d> control_points; ///< 路径的控制点，{{x,y},{}, ...}
};

/**
 * 地图信息
 */
struct MapInfo
{
    Header header;            ///< 地图id，地图名称，当前时间，map_id为地图的唯一id
    double resolution;        ///< 分辨率，每个正方形栅格/像素的宽度，单位 m
    uint32_t width;           ///< 地图宽度，多少个栅格/像素宽度
    uint32_t height;          ///< 地图高度，多少个栅格/像素高度
    Pose2d origin;            ///< {x(m) y(m) theta(rad)}
                              ///< 地图原点在真实地图下的坐标，指地图原点对应的实际位置坐标。
                              ///< 一张地图中，左下角为地图原点；
    MapFormat format;         ///< 地图格式
    std::vector<int8_t> data; ///< 地图数据信息
};

/**
 *  @brief 栅格地图
 *  @details
 *  Header header;            // 地图id，地图名称，当前时间，map_id为地图的唯一id\n
 *  double resolution;        // 分辨率，每个正方形栅格的宽度，单位 m\n
 *  uint32_t width;           // 地图宽度，多少个栅格宽度\n
 *  uint32_t height;          // 地图高度，多少个栅格高度\n
 *  Pose2d origin;            // {x(m) y(m) theta(rad)}
 *                            // 栅格地图原点在真实地图下的坐标，指栅格原点对应的实际位置坐标。
 *                            // 一张栅格地图中，左下角为栅格地图原点；\n
 *  MapFormat format;         // 地图格式，=MapFormat::OCCUPANCY_GRID\n
 *  std::vector<int8_t> data; // 地图数据信息；0 表示可通行，100 表示被占用，-1 表示未知
 */
typedef MapInfo OccupancyGridMap;

/**
 *  @brief Base64编码的png地图图片
 *  @details
 *  Header header;            // 地图id，地图名称，当前时间，map_id为地图的唯一id\n
 *  double resolution;        // 分辨率，每个正方形像素表示的宽度，单位 m\n
 *  uint32_t width;           // 地图宽度，多少个像素宽度\n
 *  uint32_t height;          // 地图高度，多少个像素高度\n
 *  Pose2d origin;            // {x(m) y(m) theta(rad)}
 *                            // 地图原点在真实地图下的坐标，指地图原点对应的实际位置坐标。
 *                            // 一张地图中，左下角为地图原点；\n
 *  MapFormat format;         // 地图格式，=MapFormat::BASE64_PNG\n
 *  std::vector<int8_t> data; // 地图数据信息；Base64编码的png地图图片，可以将data类型转换为string类型使用
 */
typedef MapInfo Base64PngMap;

/**
 * 地图中的虚拟区域
 */
struct MapVirtualArea
{
    Header header;               ///< 虚拟区域的id，虚拟区域的名称，当前时间，虚拟区域所在地图的id
    MapVirtualAreaType type;     ///< 虚拟区域的类型
    MapVirtualAreaShape shape;   ///< 虚拟区域形状
    double width_speed;          ///< 虚拟墙的宽度/膨胀半径/减速区域的最大速度
    std::vector<Point2d> vertex; ///< 虚拟区域的顶点 {{x(m) y(m)},{}, ...}
                                 ///< 直线、多边形：按照顺时针顺序把顶点加入到 vertex 中
                                 ///< 圆弧：圆弧起点、圆弧上一点、圆弧终点
                                 ///< 圆形：圆上按顺序排序的任意不共线三个以上的点(包含3个)
};

/**
 * 包含当前地图、当前地图上的站点、当前地图上的路径、当前地图上的虚拟区域信息
 */
struct MapAllInfo
{
    MapInfo map;                               ///< 当前地图信息
    std::vector<StationMark> stations;         ///< 当前地图上的站点信息
    std::vector<PathStation> paths;            ///< 当前地图上的路径信息
    std::vector<MapVirtualArea> virtual_areas; ///< 当前地图上的虚拟区域信息
};

/**
 * IP地址
 */
struct IpAddressInfo
{
    std::string name;         ///< 连接名称
    std::string type;         ///< 类型
    std::string device;       ///< 网卡名称
    std::string ipv4_ip;      ///< IPv4地址及CIDR码，为空时无效
    std::string ipv4_gateway; ///< 网关
    std::string ipv4_method;  ///< 自动分配或者手动连接，对应字段 auto, manual
    std::string ipv4_dns;     ///< 第一个DNS
    std::string ipv6_ip;      ///< IPv6地址及CIDR码，为空时无效
    std::string ipv6_gateway;
};
/**
 * agv 到点后二次调整位置参数设置
 */
struct AdjustParam
{
    bool enable;         ///< 是否要二次调整agv位置，true-调整；false不调整
    bool forward_flag;   ///< agv 调整方向，true，向车头方向调整，false，向车尾方向调整
    double max_distance; ///< agv 单次调整的最远距离
    double max_angle;    ///< agv 单次调整的最大角度
};
/**
 * 使 agv 导航到目标位置（控制信息）
 */
struct NavGoalType
{
    Header header;                        ///< 任务id，任务名称，当前时间，地图id
    NavType type;                         ///< 导航类型
    Pose2d target_pose;                   ///< 目标位姿 {x(m) y(m) theta(rad)}
                                          ///< 导航类型为自由导航到任意点时有效，其他无效
    std::vector<std::string> stations_id; ///< 导航经过的站点id,最后一个站点为导航目标位置
                                          ///< 导航类型为自由导航到站点时，或路径导航到站点时有效，其他无效
    bool forward_flag;                    ///< agv 正向行驶或倒车行驶
    bool goal_end_rotate;                 ///< 到达目标点后是否根据站点方向旋转，true：旋转
                                          ///< false：不旋转
    AdjustParam secondary_adjustment;     ///< 到达目标点后是否进行二次调整，贴合目标点位置, true：到点调整
                                          ///< false：到点不调整
    Speed max_vel;                        ///< 最大速度v,w
};

/**
 * @brief 导航状态信息  / 自动充电状态信息
 * @details
 * 导航模式时，获取导航状态信息\n
 * 自动充电模式时，获取自动充电状态信息，type与current_trajectory无效
 *  */
struct NavInfo
{
    Header header;    ///< 任务id，任务名称，当前时间，地图id
    NavStatus status; ///< 导航状态
    [[deprecated("Since 0.7.0: use nav_type instead.")]]
    NavType type;                            ///< 导航类型
    NavType nav_type;                        ///< 导航类型
    AutoChargingType auto_charging_type;     ///< 自动充电类型
    StationMark goal_station;                ///< agv行驶路径目标站点
    std::vector<Point2d> current_trajectory; ///< 还没经过的路径点 {{x(m) y(m)},{}, ...}
};

/**
 * @brief 自动充电信息
 * @since 0.7.0
 */
struct AutoChargingCommand
{
    Header header;                       ///< 任务id，任务名称，当前时间，地图id
    AutoChargingType auto_charging_type; ///< 自动充电类型
    std::string cp_station_id;           ///< 站点id，上桩任务中，表示去往哪个充电站点进行充电；为空时前往最近充电站点
    std::string leave_to_station_id;     ///< 站点id，下桩任务中，表示下桩导航到哪个站点； 为空时导航到充电站点
    Speed max_speed;                     ///< 充电过程中的最大行驶速度
};

/**
 * 配置要更新固件的模块及固件路径
 */
struct FirmwareUpdateParam
{
    FirmwareUpdateMode left_motor;   ///< 左电机固件更新信息配置
    FirmwareUpdateMode right_motor;  ///< 右电机固件更新信息配置
    FirmwareUpdateMode master_board; ///< 接口板固件更新信息配置
    std::string firmware_file_path;  ///< 代表固件包的路径 例如 "/root/update.firm"
};

/**
 * 固件更新过程信息
 */
struct FirmwareUpdateProcessInfo
{
    std::string update_info; ///< 当前固件更新的步骤信息，failed 为升级失败,
                             ///< none 为无固件更新任务
    double update_progress;  ///< 固件更新进度信息，1.0 代表升级成功
};

struct CalibrationProcessInfo
{
    Header header;                 ///< 任务id，任务名称，当前时间，地图id
    CalibrationType type;          ///< 标定类型
    CalibrationStatus status;      ///< 标定状态
    uint32_t collected_data_count; ///< 采集到多少组数据
};

/**
 * RTDE菜单
 */
struct RtdeRecipe
{
    bool to_server;                    ///< 输入/输出
    int chanel;                        ///< 通道
    double frequency;                  ///< 更新频率
    int trigger;                       ///< 触发方式(该功能暂未实现): 0 - 周期; 1 - 变化
    std::vector<std::string> segments; ///< 字段列表
};

enum error_type
{
    parse_error      = -32700, ///< 解析错误
    invalid_request  = -32600, ///< 无效请求
    method_not_found = -32601, ///< 方法未找到
    invalid_params   = -32602, ///< 无效参数
    internal_error   = -32603, ///< 内部错误
    server_error,              ///< 服务器错误
    invalid                    ///< 无效
};

enum ExceptionCode
{
    EC_DISCONNECTED     = -1,  ///< 断开连接
    EC_NOT_LOGINED      = -2,  ///< 未登录
    EC_INVAL_SOCKET     = -3,  ///< 无效套接字
    EC_REQUEST_BUSY     = -4,  ///< 请求繁忙
    EC_SEND_FAILED      = -5,  ///< 发送失败
    EC_RECV_TIMEOUT     = -6,  ///< 接收超时
    EC_RECV_ERROR       = -7,  ///< 接收错误
    EC_PARSE_ERROR      = -8,  ///< 解析错误
    EC_INVALID_REQUEST  = -9,  ///< 无效请求
    EC_METHOD_NOT_FOUND = -10, ///< 方法未找到
    EC_INVALID_PARAMS   = -11, ///< 无效参数
    EC_INTERNAL_ERROR   = -12, ///< 内部错误
    EC_SERVER_ERROR     = -13, ///< 服务器错误
    EC_INVALID          = -14  ///< 无效
};

class AgvcException : public std::exception
{
public:
    AgvcException(int code, const std::string &prefix, const std::string &message) noexcept
        : code_(code), message_(prefix + "-" + message)
    {
    }

    AgvcException(int code, const std::string &message) noexcept : code_(code), message_(message) {}

    error_type type() const
    {
        if (code_ >= -32603 && code_ <= -32600) {
            return static_cast<error_type>(code_);
        } else if (code_ >= -32099 && code_ <= -32000) {
            return server_error;
        } else if (code_ == -32700) {
            return parse_error;
        }
        return invalid;
    }

    int code() const { return code_; }
    const char *what() const noexcept override { return message_.c_str(); }

private:
    int code_;
    std::string message_;
};

inline const char *returnValue2Str(int retval)
{
    static const char *retval_str[] = {
#define ENUM_ITEM(n, v, s) s,
        ENUM_AgvcErrorCodes_DECLARES
#undef ENUM_ITEM
    };

    enum agvc_index
    {
#define ENUM_ITEM(n, v, s) n##_INDEX,
        ENUM_AgvcErrorCodes_DECLARES
#undef ENUM_ITEM
    };

    int index = -1;

#define ENUM_ITEM(n, v, s) \
    if (retval == v)       \
        index = n##_INDEX;
    ENUM_AgvcErrorCodes_DECLARES
#undef ENUM_ITEM

        if (index == -1)
    {
        index = AGVC_ERR_UNKOWN;
    }

    return retval_str[(unsigned)index];
}

} // namespace agvc_interface

#if defined ENABLE_JSON_TYPES
#include "bindings/jsonrpc/json_types.h"
#endif

#endif
