package ${basePackage}.frame.schedule;

import ${basePackage}.module.system.ent.Schedule;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledFuture;

public class Scheduler extends ThreadPoolTaskScheduler {

    private Map<String, TaskWrapper> taskMap;

    public Scheduler() {
        taskMap = new HashMap<>();
        setPoolSize(4);
        initialize();
    }

    public boolean createOrRepeat(RunTask task) {
        if (taskMap.containsKey(task.taskId())) {
            ScheduledFuture<?> scheduledFuture = taskMap.get(task.taskId()).future;
            scheduledFuture.cancel(false);
        }
        taskMap.put(task.taskId(), new TaskWrapper(
                task.taskId(),
                task.taskName(),
                true,
                (Class<RunTask>) task.getClass(),
                task.schedule(this)
        ));
        return true;
    }

    public boolean remove(String taskId) {
        if (taskMap.containsKey(taskId)) {
            ScheduledFuture<?> scheduledFuture = taskMap.get(taskId).future;
            scheduledFuture.cancel(false);
            taskMap.remove(taskId);
        }
        return true;
    }

    public boolean stop(String taskId) {
        if (taskMap.containsKey(taskId)) {
            taskMap.get(taskId).run = false;
            ScheduledFuture<?> scheduledFuture = taskMap.get(taskId).future;
            scheduledFuture.cancel(false);
        }
        return true;
    }

    public List<Schedule> taskList() {
        List<Schedule> result = new ArrayList<>();
        for (TaskWrapper taskWrapper : taskMap.values()) {
            Schedule schedule = new Schedule();
            schedule.setId(taskWrapper.taskId);
            schedule.setName(taskWrapper.taskName);
            schedule.setRun(taskWrapper.run);
            result.add(schedule);
        }
        return result;
    }

    class TaskWrapper {
        String taskId;
        String taskName;
        boolean run;
        Class<RunTask> target;
        ScheduledFuture<?> future;

        public TaskWrapper(String taskId, String taskName, boolean run, Class<RunTask> target, ScheduledFuture<?> future) {
            this.taskId = taskId;
            this.taskName = taskName;
            this.run = run;
            this.target = target;
            this.future = future;
        }
    }
}