package handler

import (
	"cicv-data-closedloop/amd64/dispatch_server/package/domain"
	entity2 "cicv-data-closedloop/amd64/dispatch_server/package/entity"
	"cicv-data-closedloop/amd64/dispatch_server/package/global"
	"cicv-data-closedloop/amd64/dispatch_server/package/infra"
	"cicv-data-closedloop/common/config/c_log"
	"cicv-data-closedloop/common/entity"
	"github.com/gin-gonic/gin"
	"net/http"
)

/*
{
  "projectId": "项目ID",
  "algorithmObjectKey": "算法在阿里云的存储路径",
  "userId": "用户ID",
  "parallelism": 10,
  "tasks": [
    {
      "info": {
        "project_id": "项目ID",
        "task_id": "任务ID",
        "task_path": "任务结果路径",
        "default_time": "最大仿真时间"
      },
      "scenario": {
        "scenario_osc": "xosc或xml路径",
        "scenario_odr": "xodr路径",
        "scenario_osgb": "osgb路径"
      },
      "vehicle": {
        "model": {
          "model_label": "模型标签"
        },
        "dynamics": {
            "dynamics_maxspeed": 0.0, //最大速度（千米/小时）
            "dynamics_enginepower": 0.0, // 发动机功率（千瓦）
            "dynamics_maxdecel": 0.0, // 最大减速度（米/秒2）
            "dynamics_maxsteering": 0.0, // 最大减速度（米/秒2）
            "dynamics_mass": 0.0, // 质量（千克）
            "dynamics_frontsurfaceeffective": 0.0, // 前表面有效面积（平方米）
            "dynamics_airdragcoefficient": 0.0, // 空气阻力系数
            "dynamics_rollingresistance": 0.0, // 滚动阻力系数
            "dynamics_wheeldiameter": 0.0, // 车轮直径（米）
            "dynamics_wheeldrive": "wheel_drive_front", // 驱动方式
            "dynamics_overallefficiency": 0.0, // 总效率
            "dynamics_distfront": 0.0, // 车前距（米）
            "dynamics_distrear": 0.0, // 车后距（米）
            "dynamics_distleft": 0.0, // 车左距（米）
            "dynamics_distright": 0.0, // 车右距（米）
            "dynamics_distheight": 0.0, // 车高（米）
            "dynamics_wheelbase": 0.0 // 轴距（米）
        },
        "sensors": {
          "camera": [
            {
              "sensor_name": "",
              "sensor_near": 0,
              "sensor_far": 0,
              "sensor_x": 0,
              "sensor_y": 0,
              "sensor_z": 0,
              "sensor_h": 0,
              "sensor_p": 0,
              "sensor_r": 0,
              "sensor_fovH": 0,	// 水平视场角
              "sensor_fovV": 0,	// 垂直视场角
              "sensor_resolution": 0, // 水平视场角偏移量
              "sensor_frameRate": 0	// 垂直视场角偏移量
            }
          ],
          "OGT": [
            {
                "sensor_name": "", // 传感器名称
                "sensor_near": 0, // 盲区距离
                "sensor_far": 0, // 探测距离
                "sensor_x": 0, // 传感器横向偏移量（x轴）
                "sensor_y": 0, // 传感器纵向偏移量（y轴）
                "sensor_z": 0, // 传感器安装高度（z轴）
                "sensor_h": 0, // 传感器横摆角
                "sensor_p": 0, // 传感器俯仰角
                "sensor_r": 0, // 传感器横滚角
                "sensor_fovHLeft": 0, // 水平现场角左
                "sensor_fovHRight": 0, // 水平现场角右
                "sensor_fovVTop": 0, // 垂直现场角顶
                "sensor_fovVBottom": 0, // 垂直现场角底
                "sensor_filter": "0,5,6", // 目标物筛选序列（0,1,2）
                "sensor_display": false, // 显示目标物
                "sensor_maxObjects": 0, // 最大目标物个数
                "sensor_port": 0 // 端口
            },
            {
              "sensor_name": "",
              "sensor_near": 0,
              "sensor_far": 0,
              "sensor_x": 0,
              "sensor_y": 0,
              "sensor_z": 0,
              "sensor_h": 0,
              "sensor_p": 0,
              "sensor_r": 0,
              "sensor_fovHLeft": 0,
              "sensor_fovHRight": 0,
              "sensor_fovVTop": 0,
              "sensor_fovVBottom": 0,
              "sensor_filter": "1,2,3,4",
              "sensor_display": false,
              "sensor_maxObjects": 0,
              "sensor_port": 0
            }
          ]
        }
      }
    }
  ]
}
*/

func StartProject(c *gin.Context) {
	projectStartParam := new(entity2.Project)
	if err := c.ShouldBindJSON(&projectStartParam); err != nil {
		c_log.GlobalLogger.Error("项目启动接收请求参数报错：", err)
		c.JSON(http.StatusBadRequest, entity.HttpResult{Status: false, Code: "1003", Message: "请求参数格式错误。"})
		return
	}
	// ------------ 维护一个运行任务队列，绑定用户id和节点名称，供下面两个判断同时使用（使用redis的队列）
	userId := projectStartParam.UserId               // 用户ID
	taskReceived := projectStartParam.Tasks          // 接收到的所有任务
	userParallelism := projectStartParam.Parallelism // 用户的并行度上限
	algorithmObjectKey := projectStartParam.AlgorithmObjectKey

	// 1 判断用户并行度
	for _, task := range taskReceived {
		global.RunTaskMutex.Lock()
		// 1 判断用户并行度是否有剩余，有剩余则加入集群等待队列，并从用户等待队列中拿出，没有剩余则不需要改动
		if domain.CanRunUser(userId, userParallelism) { // 可以运行
			err := domain.AddWaitingCluster(userId, userParallelism, algorithmObjectKey, task)
			if err != nil {
				infra.GlobalLogger.Errorf("将任务 %v 添加到集群等待队列失败，错误信息为：%v", task, err)
				continue
			}
		} else { // 不能运行
			err := domain.AddWaitingUser(userId, userParallelism, algorithmObjectKey, task)
			if err != nil {
				infra.GlobalLogger.Errorf("将任务 %v 添加到集群等待队列失败，错误信息为：%v", task, err)
				continue
			}
		}
		global.RunTaskMutex.Unlock()
	}

	// 4 返回
	c.JSON(http.StatusOK, entity.HttpResult{Status: true, Code: "2000", Message: "项目启动请求已被成功接收，等待调度处理。"})
}
