package xyz.wbsite.frame.schedule;

import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import xyz.wbsite.frame.base.LocalData;
import xyz.wbsite.frame.base.LogTaskEntity;
import xyz.wbsite.frame.provider.LogTaskCollector;
import xyz.wbsite.frame.utils.LogUtil;

import java.util.Date;
import java.util.concurrent.ScheduledFuture;

/**
 * 抽象任务
 *
 * @author wangbing
 * @version 0.0.1
 * @since 2020-01-01
 */
public abstract class RunTask implements Runnable {

    public abstract String taskId();

    protected abstract void task();

    public String taskName() {
        return "";
    }

    public String taskNote() {
        return "";
    }

    @Override
    public void run() {
        LogTaskEntity logTaskEntity = new LogTaskEntity();
        logTaskEntity.setTaskId(taskId());
        logTaskEntity.setTaskName(taskName());
        logTaskEntity.setStartTime(new Date());
        try {
            boolean before = before();
            if (before) {
                task();
            }
            after();
            logTaskEntity.setExecState("1");
            logTaskEntity.setExecResult("成功");
            logTaskEntity.setEndTime(new Date());
        } catch (Exception e) {
            exception(e);
            // 保证异常信息不会超过字段长度
            String trace = LogUtil.getTrace(e);
            if (trace.length() > 496) {
                trace = trace.substring(0, 496);
            }
            logTaskEntity.setExecState("0");
            logTaskEntity.setExecResult(String.format("失败[%s]", trace));
            logTaskEntity.setEndTime(new Date());
        }
        try {
            // 任务执行结果
            logTaskEntity.setExecTime((int) (logTaskEntity.getEndTime().getTime() - logTaskEntity.getStartTime().getTime()));
            LogTaskCollector logtaskManager = LocalData.getBean(LogTaskCollector.class);
            if (logtaskManager != null) logtaskManager.collector(logTaskEntity);
            // todo 考虑是否将任务的异常归为故障
        } catch (Exception ignored) {

        }
    }

    /**
     * 任务执行前执行
     *
     * @return 是否继续执行任务
     */
    protected boolean before() {
        return true;
    }

    /**
     * 任务执行后执行
     */
    protected void after() {
    }

    /**
     * 执行任务异常处理
     */
    protected void exception(Exception e) {
        e.printStackTrace();
    }

    public abstract ScheduledFuture<?> schedule(ThreadPoolTaskScheduler poolTaskScheduler);
}