package com.inspect.job.util;

import com.inspect.base.core.utils.ExceptionUtil;
import com.inspect.base.core.utils.SpringUtils;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.core.utils.bean.BeanUtils;
import com.inspect.job.domain.SysJob;
import com.inspect.job.domain.SysJobLog;
import com.inspect.job.service.ISysJobLogService;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractQuartzJob implements Job {
    private static final Logger logger = LoggerFactory.getLogger(AbstractQuartzJob.class);
    private static final ThreadLocal<Date> threadLocal = new ThreadLocal<>();

    @Override
    public void execute(JobExecutionContext context) {
        SysJob sysJob = new SysJob();
        try {
            BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get("TASK_PROPERTIES"));
            preJob();
            doExecute(context, sysJob);
            postJob(sysJob, null);
        } catch (Exception e) {
            logger.error("[GABRIEL] Job execute exception", e);
            this.postJob(sysJob, e);
        }
    }

    protected void preJob() {
        threadLocal.set(new Date());
    }

    protected void postJob(SysJob sysJob, Exception e) {
        Date startTime = threadLocal.get();
        threadLocal.remove();

        Date endTime = new Date();
        SpringUtils.getBean(ISysJobLogService.class).addJobLog(SysJobLog
                .builder()
                .jobName(sysJob.getJobName())
                .jobGroup(sysJob.getJobGroup())
                .invokeTarget(sysJob.getInvokeTarget())
                .startTime(startTime)
                .stopTime(endTime)
                .jobMessage(sysJob.getJobName() + " cost: " + (endTime.getTime() - startTime.getTime()) + "ms")
                .status(e == null ? "0" : "1")
                .exceptionInfo(e == null ? "" : StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000))
                .build());
    }

    protected abstract void doExecute(JobExecutionContext context, SysJob job) throws Exception;
}
