package com.ms.biz.common;

import com.jinritemai.cloud.base.core.util.LogUtils;
import com.ms.biz.tool.CommonTool;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.UUID;
import java.util.concurrent.Executor;

@Slf4j
public abstract class TaskBaseService implements TaskHandler {

    @Getter
    protected boolean isCirculate = false;
    @Getter
    protected int intervalTimeSecond = 2;
    @Getter
    protected int corePoolSiz = 4;
    @Getter
    protected int maxPoolSize = 10000;
    @Getter
    protected int queueCapacity = 50000;
    @Getter
    protected String taskExecutorName = "TaskPool";

    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 为了避免线程池满了，导致定时任务无法执行，这里多加一个线程
        executor.setCorePoolSize(getCorePoolSiz() + 1);
        executor.setMaxPoolSize(getMaxPoolSize());
        executor.setQueueCapacity(getQueueCapacity());
        // 增加随机数，在分布式环境下，区分不同的线程池和线程，以进行分布式锁的使用
        executor.setThreadNamePrefix(getTaskExecutorName() + UUID.randomUUID());
        executor.initialize();
        return executor;
    }

    public void runTask() {
        Ret ret = lockTask();
        if(CommonTool.isFailRet(ret)){
            return;
        }
        try {
            setLogId();
            if (isPoolFull()) {
                return;
            }
            execute();
        } catch (MSException e) {
            log.info(e.getMessage());
        } catch (Throwable e) {
            log.error("任务异常退出, 任务池 " + getTaskExecutorName(), e);
        }finally {
            unlockTask(ret);
        }
    }

    protected Ret lockTask() {
        return CommonTool.successResult();
    }

    protected void unlockTask(Ret ret) {
    }

    protected void setLogId() {
        LogUtils.setLogId(getLogId() + System.currentTimeMillis());
    }

    private boolean isPoolFull() {
        ThreadPoolTaskExecutor mTaskPool = (ThreadPoolTaskExecutor) getTaskPool();
        if (mTaskPool.getActiveCount() == mTaskPool.getCorePoolSize()) {
            log.info("线程池【" + mTaskPool.getThreadNamePrefix() + "】已满，不再执行任务");
            return true;
        }
        return false;
    }

    public void execute() {
        String threadInfo = getThreadPoolInfo();
        log.info(threadInfo);


        log.info("开始执行任务");

        Object getTaskRet = getTask();
        log.info("getTask结束");

        Object processTaskRet = processTask(getTaskRet);
        log.info("processTask结束");

        clearTask(processTaskRet);
        log.info("clearTask结束");

        log.info("执行任务结束");
    }

    protected String getLogId() {
        return getTaskExecutorName();
    }

    protected abstract Executor getTaskPool();

    protected String getThreadPoolInfo() {
        ThreadPoolTaskExecutor mTaskPool = (ThreadPoolTaskExecutor) getTaskPool();
        String currentThreadName = Thread.currentThread().getName();
        int activeThreads = mTaskPool.getActiveCount();
        int poolSize = mTaskPool.getPoolSize();
        int maxPoolSize = mTaskPool.getMaxPoolSize();
        int queueSize = mTaskPool.getThreadPoolExecutor().getQueue().size();
        return String.format("异步方法从线程：%s中被调用！状态 - 活跃线程数：%d, 线程池大小：%d, 最大线程池大小：%d, 队列大小：%d", currentThreadName, activeThreads, poolSize, maxPoolSize, queueSize);
    }

}

