package cn.iocoder.yudao.module.system.service.tool;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotAcceptTaskDTO;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO;
import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDataDTO;
import cn.iocoder.yudao.module.mqtt.enums.task.ExecutionTypeEnum;
import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO;
import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils;
import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.config.dto.TaskOrderConfigDTO;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.controller.admin.tool.dto.CleanAgvDTO;
import cn.iocoder.yudao.module.system.controller.admin.tool.dto.SendMsgToMqttDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnMsgDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotWarnMsgMapper;
import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.enums.item.PositionMapItemEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotWarnType;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotCommandTypeEnum;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService;
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Slf4j
@Service
@Validated
public class ToolsServiceImpl implements ToolsService {

    /*@Resource
    private CommonApi commonApi;*/

    @Autowired
    private MqttUtils mqttUtils;

    @Resource
    private CommonConfigMapper configMapper;

    @Resource
    private RobotWarnMsgService warnMsgService;

    @Resource
    private RobotWarnMsgMapper warnMsgMapper;

    @Resource
    private RobotInformationService informationService;

    @Autowired
    private RobotInformationService robotInformationService;

    @Resource
    private PositionMapItemService positionMapItemService;

    @Resource
    private PositionMapService positionMapService;

    @Autowired
    private ZnConfigConstant znConfigConstant;

    /**
     * 发送时间、优先级、距离的权重给PP
     *
     * @return
     */
    @Override
    public String sendPPsortConfig() {

        CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
                .eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.CHARG_CONFIG.getType()));

        if (ObjectUtil.isEmpty(commonConfigDO) || ObjectUtil.isEmpty(commonConfigDO.getConfigStr())) {
            log.info("没有配置路径规划权重");
            addWarnMsg();
            return "没有配置路径规划权重";
        }

        CommonConfigVO chargeConfig = JSONUtil.toBean(commonConfigDO.getConfigStr(), CommonConfigVO.class);
        if (ObjectUtil.isNotEmpty(chargeConfig.getWarnWaitTime())) {
            List<RobotInformationDO> robots = informationService.getAllRobot();
            if (ObjectUtil.isNotEmpty(robots)) {
                for (RobotInformationDO robot : robots) {
//                    commonApi.commonMethodStr(String.valueOf(chargeConfig.getWarnWaitTime()),
//                            RobotTopicConstant.WARN_WAIT_TIME_TOPIC+robot.getMacAddress());
                    mqttUtils.pub(RobotTopicConstant.WARN_WAIT_TIME_TOPIC+robot.getMacAddress(),String.valueOf(chargeConfig.getWarnWaitTime()));
                }
            }
        }


        if (ObjectUtil.isEmpty(chargeConfig.getPathSortConfig())) {
            addWarnMsg();
            return "没有配置路径规划权重";
        }

        CommonConfigDO config = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
                .eq(CommonConfigDO::getConfigType, chargeConfig.getPathSortConfig()));
        if (ObjectUtil.isEmpty(config)) {
            addWarnMsg();
            return "没有配置路径规划权重";
        }

        TaskOrderConfigDTO taskOrderConfigDTO = JSONUtil.toBean(config.getConfigStr(), TaskOrderConfigDTO.class);
//        commonApi.commonMethod(taskOrderConfigDTO,
//                PathPlanningTopicConstant.SEND_SORT_CONFIG_TO_PP);
        mqttUtils.pub(PathPlanningTopicConstant.SEND_SORT_CONFIG_TO_PP,JSON.toJSONString(taskOrderConfigDTO));

        return "发送数据库权重配置成功";
    }

    /**
     * 清除交管
     *
     * @return
     */
    @Override
    public String cleanAgv(String robotNo) {
        CleanAgvDTO build = CleanAgvDTO.builder().robotNo(robotNo).build();
//        commonApi.commonMethod(build, PathPlanningTopicConstant.CLEAN_AGV);
        mqttUtils.pub(PathPlanningTopicConstant.CLEAN_AGV,JSON.toJSONString(build));
        return "清除交管成功 " + robotNo;
    }

    /**
     * 关闭任务
     * @param taskDetailId
     * @return
     */
    @Override
    public String closeTaskDetail(String taskDetailId) {
        RobotInformationDO informationDO = informationService.getRobotInformationByDetailId(taskDetailId);
        RobotClosePathPlantingDTO closePathPlanting = RobotClosePathPlantingDTO.builder()
                .robotNo(informationDO.getRobotNo())
                .id(taskDetailId)
                .build();
//        commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK);
        mqttUtils.pub(PathPlanningTopicConstant.KILL_TASK,JSON.toJSONString(closePathPlanting));

        RobotAcceptTaskDTO robotTask = new RobotAcceptTaskDTO();
        robotTask.setOrderId(taskDetailId);
        String mac = robotInformationService.getMacByRobotNo(informationDO.getRobotNo());
        robotTask.setTopic(RobotTopicConstant.ROBOT_TASK_MOVE_TOPIC + mac);
        robotTask.setExecutionType(ExecutionTypeEnum.CANCEL.getType());
//        commonApi.commonMethod(robotTask, robotTask.getTopic());
        mqttUtils.pub(robotTask.getTopic(),JSON.toJSONString(robotTask));
        return "关闭任务成功";
    }

    @Override
    public String updateWarnCode() {
        List<RobotInformationDO> robots = robotInformationService.getAllRobot();
        if (ObjectUtil.isEmpty(robots)){
            return "暂无机器人";
        }

        for (RobotInformationDO robot : robots) {
//            commonApi.commonMethodStr("请同步告警码值", RobotTopicConstant.UPDATE_ERROR_TOPIC+robot.getMacAddress());
            mqttUtils.pub(RobotTopicConstant.UPDATE_ERROR_TOPIC+robot.getMacAddress(),"请同步告警码值");
            try {
                //怕车机同时间同步对内存有影响
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return "同步完成";
    }

    @Override
    public void simulationPose() {
        if (!znConfigConstant.getIsSimulation()) {
            log.info("非仿真环境不需要同步默认的节点数据");
        }

        TenantContextHolder.setTenantId(1L);

//        CommonConfigDO config = configService.getConfig(CommandConfigTypeEnum.SIMULATION_CONFIG.getType().longValue());

        CommonConfigDO config = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
                .eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.SIMULATION_CONFIG.getType().longValue()));

        PositionMapDO positionMap = null;
        if (ObjectUtil.isEmpty(config) || ObjectUtil.isEmpty(config.getConfigStr())) {
            List<PositionMapDO> maps = positionMapService.getAllMap();
            if (ObjectUtil.isEmpty(maps)) {
                return;
            }
            positionMap = maps.get(0);
        } else {
            positionMap = positionMapService.getPositionMap(Long.valueOf(config.getConfigStr()));
        }
        if (ObjectUtil.isEmpty(positionMap)) {
            log.info("仿真环境没有地图信息");
            return;
        }

        List<RobotInformationDO> robots = robotInformationService.getAllRobot();

        if (ObjectUtil.isEmpty(robots)) {
            log.info("仿真环境没有机器人信息");
            return;
        }

        List<PositionMapItemDO> itemDOList = new ArrayList<>();
        List<PositionMapItemDO> items = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.STOP.getType());
        if (ObjectUtil.isEmpty(items) || items.size() < robots.size()) {
            List<PositionMapItemDO> itemPoses = positionMapItemService.getPositionMapItemByMapAndType(positionMap.getId(), PositionMapItemEnum.PATH.getType());
            itemDOList.addAll(itemPoses);
        } else {
            itemDOList = items;
        }

        int i = 0;
        for (RobotInformationDO robot : robots) {
            RobotSimulationPoseDataDTO poseData = new RobotSimulationPoseDataDTO();
            RobotSimulationPoseDTO simulationPoseDTO = new RobotSimulationPoseDTO();
            if (itemDOList.size() <= i) {
                continue;
            }

            poseData.setX(Double.valueOf(itemDOList.get(i).getActualLocationX()));
            poseData.setY(Double.valueOf(itemDOList.get(i).getActualLocationY()));
            poseData.setYaw(Double.valueOf(itemDOList.get(i).getLocationYaw()));
            simulationPoseDTO.setPose2d(poseData);
            simulationPoseDTO.setCommandType(RobotCommandTypeEnum.MOVE_POSE.getType());
//            commonApi.commonMethod(simulationPoseDTO, RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress());
            mqttUtils.pub(RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress(),JSON.toJSONString(simulationPoseDTO));
            log.info("仿真环境发送机器人默认点位信息 ：{}", JSON.toJSONString(poseData));
            i++;
        }
    }

    @Override
    public void sendMsgToMQTT(SendMsgToMqttDTO dto) {
//        commonApi.commonMethodStr(dto.getMsg(),dto.getTopic());
        mqttUtils.pub(dto.getTopic(),dto.getMsg());
    }


    public void addWarnMsg() {
        RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(4)
                .warnCode("NOT_PP_CONFIG")
                .robotNo("PP")
                .warnType(RobotWarnType.ROBOT_WARN.getType())
                .warnMsg("没有配置路径规划权重")
                .warnSolve("配置页面设置")
                .build();
        warnMsgService.sendWarnMsgToWebsocket(warnMsg.getWarnMsg());
        warnMsgMapper.insertBatch(Arrays.asList(warnMsg));
    }


}
