package com.cf.imes.module.executor.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * SpringBoot 装配线程池
 * @author FengJinSong
 */
@Slf4j
@Configuration
public class ThreadPoolConfig implements AsyncConfigurer {

    private static final String EXECUTOR_NAME = "asyncExecutor";

    @Value("${thread-pool.config.corePoolSize:26}")
    private Integer corePoolSize;
    @Value("${thread-pool.config.maxPoolSize:100}")
    private Integer maxPoolSize;
    @Value("${thread-pool.config.queueCapacity:200}")
    private Integer queueCapacity;
    @Value("${thread-pool.config.threadNamePrefix:AsyncThread-}")
    private String threadNamePrefix;
    @Value("${thread-pool.config.rejectedExecutionHandler:CallerRunsPolicy}")
    private String rejectedExecutionHandler;

    @Bean(name = EXECUTOR_NAME)
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        threadPoolTaskExecutor.setCorePoolSize(corePoolSize);
        // 最大线程数
        threadPoolTaskExecutor.setMaxPoolSize(maxPoolSize);
        // 阻塞队列容量
        threadPoolTaskExecutor.setQueueCapacity(queueCapacity);
        // 待任务在关机时完成--表明等待所有线程执行完
        threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
        // 线程名称前缀
        threadPoolTaskExecutor.setThreadNamePrefix(threadNamePrefix);

//        threadPoolTaskExecutor.setTaskDecorator(new ContextCopyingDecorator());



        // 设置拒绝策略
        threadPoolTaskExecutor.setRejectedExecutionHandler(getRejectedExecutionHandler(rejectedExecutionHandler));




        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }


    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return (throwable, method, obj) -> {
            log.error("[ThreadPool Exception]：Message [{}], Method [{}]", throwable.getMessage(), method.getName());
            for (Object param : obj) {
                log.error("Parameter value [{}] ", param);
            }
        };
    }

    /**
     * 根据传入的参数获取拒绝策略
     *
     * @param rejectedName 拒绝策略名，比如 CallerRunsPolicy
     * @return RejectedExecutionHandler 实例对象，没有匹配的策略时，默认取 CallerRunsPolicy 实例
     */
    public RejectedExecutionHandler getRejectedExecutionHandler(String rejectedName) {
        Map<String, RejectedExecutionHandler> rejectedExecutionHandlerMap = new HashMap<>(16);
        rejectedExecutionHandlerMap.put("CallerRunsPolicy", new ThreadPoolExecutor.CallerRunsPolicy());
        rejectedExecutionHandlerMap.put("AbortPolicy", new ThreadPoolExecutor.AbortPolicy());
        rejectedExecutionHandlerMap.put("DiscardPolicy", new ThreadPoolExecutor.DiscardPolicy());
        rejectedExecutionHandlerMap.put("DiscardOldestPolicy", new ThreadPoolExecutor.DiscardOldestPolicy());
        return rejectedExecutionHandlerMap.getOrDefault(rejectedName, new ThreadPoolExecutor.CallerRunsPolicy());
    }

//    @Slf4j
//    static class ContextCopyingDecorator implements TaskDecorator {
//        @Nonnull
//        @Override
//        public Runnable decorate(@Nonnull Runnable runnable) {
//            try {
//                RequestAttributes context = RequestContextHolder.currentRequestAttributes();  //1
//                Map<String,String> previous = MDC.getCopyOfContextMap(); 					  //2
//                SecurityContext securityContext = SecurityContextHolder.getContext();	      //3
//                return () -> {
//                    try {
//                        RequestContextHolder.setRequestAttributes(context);	 //1
//                        MDC.setContextMap(previous);					     //2
//                        SecurityContextHolder.setContext(securityContext);   //3
//                        runnable.run();
//                    } finally {
//                        RequestContextHolder.resetRequestAttributes();		// 1
//                        MDC.clear(); 										// 2
//                        SecurityContextHolder.clearContext();				// 3
//                    }
//                };
//            } catch (IllegalStateException e) {
//                return runnable;
//            }
//
//
//        }
//    }

}
//public class ThreadPoolConfig {
//    //自定义使用参数
//    @Value("${async.executor.thread.core_pool_size}")
//    private int corePoolSize;   //配置核心线程数
//    @Value("${async.executor.thread.max_pool_size}")
//    private int maxPoolSize;    //配置最大线程数
//    @Value("${async.executor.thread.queue_capacity}")
//    private int queueCapacity;
//    @Value("${async.executor.thread.name.prefix}")
//    private String namePrefix;
//    @Value("${async.executor.thread.keep_alive_seconds}")
//    private int keepAliveSeconds;
//
//    //1、自定义asyncServiceExecutor线程池
//    @Bean(name = "asyncServiceExecutor")
//    public ThreadPoolTaskExecutor asyncServiceExecutor() {
//        log.info("start asyncServiceExecutor......");
//        //在这里修改
//        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//        //配置核心线程数
//        executor.setCorePoolSize(corePoolSize);
//        //配置最大线程数
//        executor.setMaxPoolSize(maxPoolSize);
//        //设置线程空闲等待时间 s
//        executor.setKeepAliveSeconds(keepAliveSeconds);
//        //配置队列大小 设置任务等待队列的大小
//        executor.setQueueCapacity(queueCapacity);
//        //配置线程池中的线程的名称前缀
//        //设置线程池内线程名称的前缀-------阿里编码规约推荐--方便出错后进行调试
//        executor.setThreadNamePrefix(namePrefix);
//        // rejection-policy：当pool已经达到max size的时候，如何处理新任务
//        // CALLER_RUNS：不在新线程中执行任务，而是有调用者所在的线程来执行
//        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
//        //执行初始化
//        executor.initialize();
//        return executor;
//    }
//    /**
//     * 2、公共线程池,利用系统availableProcessors线程数量进行计算
//     */
//    @Bean(name = "commonThreadPoolTaskExecutor")
//    public ThreadPoolTaskExecutor commonThreadPoolTaskExecutor() {
//        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
//        int processNum = Runtime.getRuntime().availableProcessors(); // 返回可用处理器的Java虚拟机的数量
//        int corePoolSize = (int) (processNum / (1 - 0.2));
//        int maxPoolSize = (int) (processNum / (1 - 0.5));
//        pool.setCorePoolSize(corePoolSize); // 核心池大小
//        pool.setMaxPoolSize(maxPoolSize); // 最大线程数
//        pool.setQueueCapacity(maxPoolSize * 1000); // 队列程度
//        pool.setThreadPriority(Thread.MAX_PRIORITY);
//        pool.setDaemon(false);
//        pool.setKeepAliveSeconds(300);// 线程空闲时间
//        return pool;
//    }
//    //3自定义defaultThreadPoolExecutor线程池
//    @Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown")
//    public ThreadPoolExecutor systemCheckPoolExecutorService() {
//        int maxNumPool=Runtime.getRuntime().availableProcessors();
//        return new ThreadPoolExecutor(3,
//                maxNumPool,
//                60,
//                TimeUnit.SECONDS,
//                new LinkedBlockingQueue<Runnable>(10000),
//                //置线程名前缀，例如设置前缀为hutool-thread-，则线程名为hutool-thread-1之类。
//                new ThreadFactoryBuilder().setNamePrefix("default-executor-thread-%d").build(),
//                (r, executor) -> log.error("system pool is full! "));
//    }

//}


