package cn.iocoder.yudao.module.system.job.robot;

import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
import cn.iocoder.yudao.module.system.service.robot.job.AutoChargeService;
import cn.iocoder.yudao.module.system.service.robot.job.CycleService;
import cn.iocoder.yudao.module.system.service.robot.job.DistributeTasksService;
import cn.iocoder.yudao.module.system.service.robot.job.RobotTaskAutoMoveService;
import cn.iocoder.yudao.module.system.service.robot.pathplanning.RobotPathPlanningService;
import cn.iocoder.yudao.module.system.util.redis.RedissonUtils;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

import java.util.HashSet;
import java.util.Set;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REDISSON_NOT_OBTAIN_LOCK;


@Component
@Slf4j
public class RobotJob {

    @Resource
    private RedissonUtils redissonUtils;

    @Autowired
    private DistributeTasksService distributeTasksService;

    @Autowired
    private RobotTaskAutoMoveService robotTaskAutoMoveService;

    @Autowired
    private AutoChargeService autoChargeService;

    @Autowired
    private CycleService cycleService;

    @Autowired
    private RobotPathPlanningService robotPathPlanningService;

    //下发任务给车机---废弃---因为这一版没有结合路径规划
//    @XxlJob("DistributeTasksJob")
    @TenantJob
    public void distributeTasksJob() throws InterruptedException {
        log.info("----下发任务给车机----");
        RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
        if (lock.tryLock()){
            try {
                distributeTasksService.distributeTasks();
            } catch (Exception e) {
                log.error("下发任务给车机出现异常 :{}",e);
            } finally {
                lock.unlock();
            }
        }else {
            log.info("下发任务未获取到锁");
            throw exception(REDISSON_NOT_OBTAIN_LOCK);
        }
    }

    //下发自动移库任务--- 废弃---产品不要自动移库
//    @XxlJob("DistributeAutoMoveJob")
    @TenantJob
    public void distributeAutoMoveJob() throws InterruptedException {
        log.info("----下发自动移库任务----");
        Set<String> locks = new HashSet<>();
        locks.add(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
        locks.add(RobotCacheLockEnum.ROBOT_TASK_ADD_LOCK.getKey());
        RLock lock = redissonUtils.getLocks(locks);
        if (lock.tryLock()){
            try {
                robotTaskAutoMoveService.distributeAutoMoveJob();
            } catch (Exception e) {
                log.error("下发自动移库任务出现异常 :{}",e);
            } finally {
                lock.unlock();
            }
        }else {
            log.info("下发自动移库任务未获取到锁");
            throw exception(REDISSON_NOT_OBTAIN_LOCK);
        }
    }

    //下发自动充电任务
    @XxlJob("AutoChargeJob")
    @TenantJob
    public void AutoChargeJob() {

        RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
        if (lock.tryLock()){
            try {
                log.info("----下发自动充电任务----");
                autoChargeService.autoChargeJob();
            } catch (Exception e) {
                log.error("下发自动充电任务出现异常 :{}",e);
            } finally {
                lock.unlock();
            }
        }else {
            log.info("下发自动充电任务未获取到锁");
            throw exception(REDISSON_NOT_OBTAIN_LOCK);
        }
    }

    /**
     * 下发任务给路径规划
     */
    @XxlJob("DistributeTasksToPathPlanningJob")
    @TenantJob
    public void DistributeTasksToPathPlanningJob() {

        RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
        if (lock.tryLock()){
            try {
                log.info("----下发任务给路径规划----");
                robotPathPlanningService.sendTaskToPP();
            } catch (Exception e) {
                log.error("下发任务给路径规划现异常 :{}",e);
            } finally {
                lock.unlock();
            }
        }else {
            log.info("下发任务给路径规划未获取到锁");
            throw exception(REDISSON_NOT_OBTAIN_LOCK);
        }
    }



    /**
     * 创建循环任务
     */
    @XxlJob("CycleTaskJob")
    @TenantJob
    public void cycleTaskJob() {

        RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_ADD_LOCK.getKey());
        if (lock.tryLock()){
            try {
                log.info("----创建循环任务----");
                cycleService.cycleTaskJob();
            } catch (Exception e) {
                log.error("创建循环任务异常 :{}", e);
            } finally {
                lock.unlock();
            }
        }else {
            log.info("下发任务给路径规划未获取到锁");
            throw exception(REDISSON_NOT_OBTAIN_LOCK);
        }
    }
}
