/*
  控制命令
*/
#pragma once

#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ----------------------------------------------------------------- */
#include "module/chassis.h"
#include "module/gimbal.h"
#include "module/shoot.h"
#if CMD_RCTypeTable_Index == 0
#include "device/dr16.h"
#elif CMD_RCTypeTable_Index == 1
#include "device/at9s_pro.h"
#elif CMD_RCTypeTable_Index == 2
#include "device/vt13.h"
#endif

/* Exported constants ------------------------------------------------------- */
#define CMD_OK (0)        /* 运行正常 */
#define CMD_ERR_NULL (-1) /* 运行时发现NULL指针 */    
#define CMD_ERR_ERR (-2)  /* 运行时发现了其他错误 */
#define CMD_ERR_SOURCE (-3) /* 运行时配置了不存在的输入源 */

/* Exported macro ----------------------------------------------------------- */
#define CMD_RCTypeTable_Index 0 /* 0:DR16 1:AT9S 2:VT13 */

#if CMD_RCTypeTable_Index == 0
#define CMD_RCType_TABLE(X) X(dr16, DR16)
#elif CMD_RCTypeTable_Index == 1
#define CMD_RCType_TABLE(X) X(at9s, AT9S)
#elif CMD_RCTypeTable_Index == 2
#define CMD_RCType_TABLE(X) X(vt13, VT13)
#endif

#if CMD_RCTypeTable_Index == 1
#define CMD_NOPC_FLAG
#endif
#define CMDMACRO_NAME_EXPANSION(name, NAME) NAME##_t name
#define CMDMACRO_VAR_RCDATA(name, NAME) NAME##_DataRC_t name;
#define CMDMACRO_VAR_PCDATA(name, NAME) NAME##_DataPC_t name;
#define CMDMACRO_VAR_LASTPCDATA(name, NAME) NAME##_DataPC_t last##name;
/* Exported types ----------------------------------------------------------- */ 
#define CMD_REFEREE_MAX_NUM (3) /* 发送命令限定的最大数量 */
/* 输入源枚举 */
typedef enum {
  CMD_SRC_RC=0,      /* 遥控器 */
  CMD_SRC_PC,      /* 键盘鼠标 */
  CMD_SRC_NUC,     /* 上位机 */
  CMD_SRC_REF, /* 裁判系统 */
  CMD_SRC_NUM
} CMD_InputSource_t;

/* RC part begin-------------------------------------- */

typedef struct {
  bool online;
  enum {DR16=0, AT9S} type;
  CMD_RCType_TABLE(CMDMACRO_VAR_RCDATA)
  #undef CMDMACRO_VAR_RCDATA           
} CMD_Input_RC_t;//或者这里直接把CMD_Input_RC_t前向声明了，看哪个好看

/* RC part end---------------------------------------- */

/* PC part begin-------------------------------------- */
typedef enum {
  CMD_MODULE_NONE    = 0,
  CMD_MODULE_CHASSIS = (1 << 0),
  CMD_MODULE_GIMBAL  = (1 << 1), 
  CMD_MODULE_SHOOT   = (1 << 2),
  CMD_MODULE_ALL     = (CMD_MODULE_CHASSIS | CMD_MODULE_GIMBAL | CMD_MODULE_SHOOT)
} CMD_ModuleMask_t;
/* 键盘按键值 */
typedef enum {
  CMD_KEY_W = 0,
  CMD_KEY_S,
  CMD_KEY_A,
  CMD_KEY_D,
  CMD_KEY_SHIFT,
  CMD_KEY_CTRL,
  CMD_KEY_Q,
  CMD_KEY_E,
  CMD_KEY_R,
  CMD_KEY_F,
  CMD_KEY_G,
  CMD_KEY_Z,
  CMD_KEY_X,
  CMD_KEY_C,
  CMD_KEY_V,
  CMD_KEY_B,
  CMD_L_CLICK,
  CMD_R_CLICK,
  CMD_M_CLICK,
  CMD_KEY_NUM,
} CMD_PCValue_t;
typedef enum {
  CMD_ACTIVE_RISING_EDGE, /* 按下时触发 */
  CMD_ACTIVE_FALLING_EDGE,   /* 抬起时触发 */
  CMD_ACTIVE_PRESSED,  /* 按住时触发 */
} CMD_TriggerType_t;

/* 行为值序列 */
typedef enum {
  CMD_BEHAVIOR_FORE = 0,       /* 向前 */
  CMD_BEHAVIOR_BACK,           /* 向后 */
  CMD_BEHAVIOR_LEFT,           /* 向左 */
  CMD_BEHAVIOR_RIGHT,          /* 向右 */
  CMD_BEHAVIOR_ACCELERATE,     /* 加速 */
  CMD_BEHAVIOR_DECELEBRATE,    /* 减速 */
  CMD_BEHAVIOR_FIRE,           /* 开火 */
  CMD_BEHAVIOR_FIRE_MODE,      /* 切换开火模式 */
  CMD_BEHAVIOR_BUFF,           /* 打符模式 */
  CMD_BEHAVIOR_AUTOAIM,        /* 自瞄模式 */
  CMD_BEHAVIOR_OPENCOVER,      /* 弹舱盖开关 */
  CMD_BEHAVIOR_ROTOR,          /* 小陀螺模式 */
  CMD_BEHAVIOR_REVTRIG,        /* 反转拨弹 */
  CMD_BEHAVIOR_FOLLOWGIMBAL35, /* 跟随云台呈35度 */
  CMD_BEHAVIOR_GIMBAL_MODE,    /* 切换云台模式 */
  CMD_BEHAVIOR_NUM,
} CMD_Behavior_t;
typedef struct {
  CMD_PCValue_t key;
  CMD_TriggerType_t trigger_type;
} CMD_KeyMapItem_t;

/* 行为映射的对应按键数组 */
typedef struct {
  CMD_KeyMapItem_t key_map[CMD_BEHAVIOR_NUM];
} CMD_KeyMap_Params_t;

typedef struct {
  float sens_mouse;       /* 鼠标灵敏度 */
  float move_sense;        /* 移动灵敏度 */
  float move_fast_sense;   /* 快速移动灵敏度 */
  float move_slow_sense;   /* 慢速移动灵敏度 */
} CMD_PC_Sensitivity_t;

typedef struct {
  CMD_KeyMap_Params_t map; /* 按键映射行为命令 */
  CMD_PC_Sensitivity_t sensitivity; /* PC灵敏度设置 */
}CMD_PCParams_t;
#ifndef CMD_NOPC_FLAG
typedef struct {
  bool online;
  CMD_RCType_TABLE(CMDMACRO_VAR_PCDATA)
  CMD_RCType_TABLE(CMDMACRO_VAR_LASTPCDATA)
  #undef CMDMACRO_VAR_PCDATA
  #undef CMDMACRO_VAR_LASTPCDATA
}CMD_Input_PC_t;
#else
  typedef struct {
  bool online;
}CMD_Input_PC_t;
#endif
/* PC part end---------------------------------------- */

/* NUC part begin------------------------------------- */
typedef struct {
  bool online;
  struct {
    float delta_yaw;
    float delta_pit;
  }gimbal;
  struct {
    float expectedSpeed;
    bool fire;
  }shoot;
}CMD_Input_NUC_t;

/* NUC part end--------------------------------------- */

/* REF part begin------------------------------------- */
typedef struct {
  bool online;
}CMD_Input_REF_t;

/* REF part begin------------------------------------- */

/* 底盘控制命令 */
typedef struct {
  CMD_InputSource_t source;
  Chassis_CMD_t cmd;
} CMD_Output_CHASSIS_t;

/* 云台控制命令 */
typedef struct {
  CMD_InputSource_t source;
  Gimbal_CMD_t cmd;
} CMD_Output_GIMBAL_t;

/* 射击控制命令 */
typedef struct {
  CMD_InputSource_t source;
  Shoot_CMD_t cmd;
} CMD_Output_SHOOT_t;

typedef struct {
  CMD_Input_RC_t rc;
  CMD_Input_PC_t pc;
  CMD_Input_NUC_t nuc;
  CMD_Input_REF_t ref;
} CMD_Input_t;
typedef struct {
  CMD_Output_CHASSIS_t chassis;
  CMD_Output_GIMBAL_t  gimbal;
  CMD_Output_SHOOT_t   shoot;
} CMD_Output_t;

typedef struct {
  CMD_InputSource_t sourcePriorityConfigs[CMD_SRC_NUM];/* 输入源优先级配置 */
  CMD_PCParams_t pc;
} CMD_Params_t;

typedef struct {
  float now;
  float dt;
  uint64_t last;
} CMD_Timer_t;
typedef struct {
  CMD_Timer_t timer;
  CMD_Params_t *params;

  CMD_Input_t input;
  CMD_Output_t output;
} CMD_t;

/* Exported functions prototypes -------------------------------------------- */
int8_t Cmd_Init(CMD_t *c, CMD_Params_t *params);
int8_t Cmd_Get(CMD_t *c, CMD_RCType_TABLE(CMDMACRO_NAME_EXPANSION));
int8_t Cmd_GenerateCommand(CMD_t *c);
#ifdef __cplusplus
}
#endif
