/*
 * CMD 模块 V2 - 主控制模块实现
 */
#include "cmd.h"
#include "bsp/time.h"
#include <stdint.h>
#include <string.h>

/* ========================================================================== */
/*                           命令构建函数                                       */
/* ========================================================================== */

/* 从RC输入生成底盘命令 */
static void CMD_RC_BuildChassisCmd(CMD_t *ctx) {
  CMD_RCModeMap_t *map = &ctx->config->rc_mode_map;
  
  /* 根据左拨杆位置选择模式 */
  switch (ctx->input.rc.sw[0]) {
      case CMD_SW_UP:
          ctx->output.chassis.cmd.mode = map->sw_left_up;
          break;
      case CMD_SW_MID:
          ctx->output.chassis.cmd.mode = map->sw_left_mid;
          break;
      case CMD_SW_DOWN:
          ctx->output.chassis.cmd.mode = map->sw_left_down;
          break;
      default:
          ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX;
          break;
  }
  
  /* 摇杆控制移动 */
  ctx->output.chassis.cmd.ctrl_vec.vx = ctx->input.rc.joy_right.x;
  ctx->output.chassis.cmd.ctrl_vec.vy = ctx->input.rc.joy_right.y;
}

/* 从RC输入生成云台命令 */
static void CMD_RC_BuildGimbalCmd(CMD_t *ctx) {
  CMD_RCModeMap_t *map = &ctx->config->rc_mode_map;
  
  /* 根据拨杆选择云台模式 */
  switch (ctx->input.rc.sw[0]) {
      case CMD_SW_UP:
          ctx->output.gimbal.cmd.mode = map->gimbal_sw_up;
          break;
      case CMD_SW_MID:
          ctx->output.gimbal.cmd.mode = map->gimbal_sw_mid;
          break;
      case CMD_SW_DOWN:
          ctx->output.gimbal.cmd.mode = map->gimbal_sw_down;
          break;
      default:
          ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX;
          break;
  }
  
  /* 左摇杆控制云台 */
  ctx->output.gimbal.cmd.delta_yaw = -ctx->input.rc.joy_left.x * 2.0f;
  ctx->output.gimbal.cmd.delta_pit = -ctx->input.rc.joy_left.y * 1.5f;
}

/* 从RC输入生成射击命令 */
static void CMD_RC_BuildShootCmd(CMD_t *ctx) {
  if (ctx->input.online[CMD_SRC_RC]) {
      ctx->output.shoot.cmd.mode = SHOOT_MODE_SINGLE;
  } else {
      ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE;
  }
  
  /* 根据右拨杆控制射击 */
  switch (ctx->input.rc.sw[1]) {
      case CMD_SW_DOWN:
          ctx->output.shoot.cmd.ready = true;
          ctx->output.shoot.cmd.firecmd = true;
          break;
      case CMD_SW_MID:
          ctx->output.shoot.cmd.ready = true;
          ctx->output.shoot.cmd.firecmd = false;
          break;
      case CMD_SW_UP:
      default:
          ctx->output.shoot.cmd.ready = false;
          ctx->output.shoot.cmd.firecmd = false;
          break;
  }
}

/* 从PC输入生成底盘命令 */
static void CMD_PC_BuildChassisCmd(CMD_t *ctx) {
  
  if (!ctx->input.online[CMD_SRC_PC]) {
      ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX;
      return;
  }
  
  ctx->output.chassis.cmd.mode = CHASSIS_MODE_FOLLOW_GIMBAL;
  
  /* WASD控制移动 */
  ctx->output.chassis.cmd.ctrl_vec.vx = 0.0f;
  ctx->output.chassis.cmd.ctrl_vec.vy = 0.0f;
  CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_CHASSIS);
}

/* 从PC输入生成云台命令 */
static void CMD_PC_BuildGimbalCmd(CMD_t *ctx) {
  CMD_Sensitivity_t *sens = &ctx->config->sensitivity;
  
  if (!ctx->input.online[CMD_SRC_PC]) {
      ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX;
      return;
  }
  
  ctx->output.gimbal.cmd.mode = GIMBAL_MODE_ABSOLUTE;
  
  /* 鼠标控制云台 */
  ctx->output.gimbal.cmd.delta_yaw = (float)-ctx->input.pc.mouse.x * ctx->timer.dt * sens->mouse_sens;
  ctx->output.gimbal.cmd.delta_pit = (float)ctx->input.pc.mouse.y * ctx->timer.dt * sens->mouse_sens * 1.5f;
  CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_GIMBAL);
}

/* 从PC输入生成射击命令 */
static void CMD_PC_BuildShootCmd(CMD_t *ctx) {
  if (!ctx->input.online[CMD_SRC_PC]) {
      ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE;
      return;
  }
  
  ctx->output.shoot.cmd.ready = true;
  ctx->output.shoot.cmd.firecmd = ctx->input.pc.mouse.l_click;

  CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_SHOOT);

}

/* 离线安全模式 */
static void CMD_SetOfflineMode(CMD_t *ctx) {
  ctx->output.chassis.cmd.mode = CHASSIS_MODE_RELAX;
  ctx->output.gimbal.cmd.mode = GIMBAL_MODE_RELAX;
  ctx->output.shoot.cmd.mode = SHOOT_MODE_SAFE;
}

/* ========================================================================== */
/*                           公开API实现                                        */
/* ========================================================================== */

int8_t CMD_Init(CMD_t *ctx, CMD_Config_t *config) {
  if (ctx == NULL || config == NULL) {
      return CMD_ERR_NULL;
  }
  
  memset(ctx, 0, sizeof(CMD_t));
  ctx->config = config;
  
  /* 初始化适配器 */
  CMD_Adapter_InitAll();
  
  /* 初始化行为处理器 */
  CMD_Behavior_Init();
  
  return CMD_OK;
}

int8_t CMD_UpdateInput(CMD_t *ctx) {
  if (ctx == NULL) {
      return CMD_ERR_NULL;
  }
  
  /* 保存上一帧输入 */
  memcpy(&ctx->last_input, &ctx->input, sizeof(ctx->input));
  
  /* 更新所有输入源 */
  for (int i = 0; i < CMD_SRC_NUM; i++) {
      CMD_Adapter_GetInput((CMD_InputSource_t)i, &ctx->input);
  }
  
  return CMD_OK;
}
typedef void (*CMD_BuildCommandFunc)(CMD_t *cmd);
typedef struct {
  CMD_InputSource_t source;
  CMD_BuildCommandFunc chassisFunc;
  CMD_BuildCommandFunc gimbalFunc;
  CMD_BuildCommandFunc shootFunc;
} CMD_SourceHandler_t;

CMD_SourceHandler_t sourceHandlers[CMD_SRC_NUM] = {
  {CMD_SRC_RC, CMD_RC_BuildChassisCmd, CMD_RC_BuildGimbalCmd, CMD_RC_BuildShootCmd},
  {CMD_SRC_PC, CMD_PC_BuildChassisCmd, CMD_PC_BuildGimbalCmd, CMD_PC_BuildShootCmd},
  {CMD_SRC_NUC, NULL, NULL, NULL},
  {CMD_SRC_REF, NULL, NULL, NULL},
};

int8_t CMD_Arbitrate(CMD_t *ctx) {
  if (ctx == NULL) {
      return CMD_ERR_NULL;
  }
  
  /* 自动仲裁：优先级 PC > RC > NUC */
  CMD_InputSource_t candidates[] = {CMD_SRC_RC, CMD_SRC_PC, CMD_SRC_NUC};
  const int num_candidates = sizeof(candidates) / sizeof(candidates[0]);
  
  /* 如果当前输入源仍然在线且有效，保持使用 */
  if (ctx->active_source < CMD_SRC_NUM && 
      ctx->active_source != CMD_SRC_REF && 
      ctx->input.online[ctx->active_source]) {
      goto seize;
  }
  
  /* 否则选择第一个可用的控制输入源 */
  for (int i = 0; i < num_candidates; i++) {
      CMD_InputSource_t src = candidates[i];
      if (ctx->input.online[src]) {
          ctx->active_source = src;
          break;
      }else {
          ctx->active_source = CMD_SRC_NUM;
          continue;
      }
  }
  ctx->output.chassis.source = ctx->active_source;
  ctx->output.gimbal.source = ctx->active_source;
  ctx->output.shoot.source = ctx->active_source;

  /* 优先级抢占逻辑 */
  seize:
  CMD_Behavior_ProcessAll(ctx, &ctx->input, &ctx->last_input, CMD_MODULE_NONE);

  return CMD_OK;
}

int8_t CMD_GenerateCommands(CMD_t *ctx) {
  if (ctx == NULL) {
      return CMD_ERR_NULL;
  }
  
  /* 更新时间 */
  uint64_t now_us = BSP_TIME_Get_us();
  ctx->timer.now = now_us / 1000000.0f;
  ctx->timer.dt = (now_us - ctx->timer.last_us) / 1000000.0f;
  ctx->timer.last_us = now_us;
  
  /* 没有有效输入源 */
  if (ctx->active_source >= CMD_SRC_NUM) {
      CMD_SetOfflineMode(ctx);
      return CMD_ERR_NO_INPUT;
  }

  sourceHandlers[ctx->output.gimbal.source].gimbalFunc(ctx);
  sourceHandlers[ctx->output.chassis.source].chassisFunc(ctx);
  sourceHandlers[ctx->output.shoot.source].shootFunc(ctx);
  return CMD_OK;
}

int8_t CMD_Update(CMD_t *ctx) {
    int8_t ret;
    
    ret = CMD_UpdateInput(ctx);
    if (ret != CMD_OK) return ret;
    
    CMD_Arbitrate(ctx);
    
    ret = CMD_GenerateCommands(ctx);
    return ret;
}
