package com.friday.distributor.scheduler.poller;

import com.friday.distributor.statemachine.TaskStateMachineHelper;
import com.google.common.collect.Lists;
import com.friday.distributor.bean.Job;
import com.friday.distributor.bean.Task;
import com.friday.distributor.queue.TaskQueueManager;
import com.friday.distributor.scheduler.ExecScheduler;
import com.friday.distributor.scheduler.QueuePoller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.friday.distributor.constant.Events.TaskEvent.FINISH_TASK;

/**
 * @Author YaoYao
 * @Date Created In 14:02 2023/3/8
 * @Description 默认队列轮询器
 * @Modified By
 */
@Slf4j
@Component("DefaultQueuePoller")
public class DefaultQueuePoller extends QueuePoller {
    @Autowired
    private PollingHelper pollingHelper;
    @Autowired
    private TaskStateMachineHelper taskStateMachineHelper;
    @Autowired
    private TaskQueueManager taskQueueManager;

    @Override
    public void polling(String queueKey, List<Task> taskList){
        try {
            if (CollectionUtils.isEmpty(taskList)) {
                return;
            }
            taskList.forEach(task -> {
                List<Job> runningJobs = task.getJobs().stream()
                        .filter(Job::running)
                        .collect(Collectors.toList());
                runningJobs.forEach(job -> pollingHelper.generalPolling(queueKey, job));
            });
            List<Job> allUnstartJobs = Lists.newArrayList();
            for(Task task : taskList){
                List<Job> unstartJobs = task.getJobs().stream()
                        .filter(Job::unStart)
                        .collect(Collectors.toList());
                allUnstartJobs.addAll(unstartJobs);
            }
            pollingHelper.mutexPolling(queueKey, this.filterUnstartJob(allUnstartJobs));
            //判断Task状态
            for(Task task : taskList){
                List<Job> undoneJobs = task.getJobs().stream()
                        .filter(Job::undone)
                        .collect(Collectors.toList());
                if(CollectionUtils.isEmpty(undoneJobs)){
                    this.freeAllExecutor(task);
                    taskStateMachineHelper.sendTaskEvent(FINISH_TASK, task);
                    taskQueueManager.removeTask(task, task.getQueueKey());
                }
            }
        } catch (Exception e){
            log.error("任务队列轮询异常", e);
        }
    }

    //将数量=Max(运行机器)的任务放入启动轮询
    private List<Job> filterUnstartJob(List<Job> unstartJobs){
        List<Job> filteredJobs = Lists.newArrayList();
        Map<String, List<Job>> sameTypeJobMap = unstartJobs.stream().collect(Collectors.groupingBy(job -> job.getTaieTenant() + job.getTaskType()));
        for(String type : sameTypeJobMap.keySet()){
            List<Job> jobs = sameTypeJobMap.get(type);
            int maxPollingNum = jobs.stream().map(j -> j.getTaskExecConfig().getMachines().size()).max(Integer::compareTo).get();
            log.info("任务{}最大同时轮询任务数为{}, 当前队列任务数为{}", type, maxPollingNum, jobs.size());
            if(jobs.size() > maxPollingNum){
                filteredJobs.addAll(jobs.subList(0, maxPollingNum));
            } else {
                filteredJobs.addAll(jobs);
            }
        }
        return filteredJobs;
    }

    private void freeAllExecutor(Task task){
        for(Job job : task.getJobs()){
            ExecScheduler execScheduler = taskQueueManager.getQueueExecScheduler(job.getQueueKey());
            execScheduler.freeExecRobot(job, "");
        }
    }



}
