package com.its.api.config;

import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PostConstruct;
import java.util.concurrent.Executor;

@EqualsAndHashCode(callSuper = true)
@Slf4j
@Data
@Configuration
public class ThreadPoolTaskExecutorConfig extends AsyncConfigurerSupport {

    private int poolCore = 0;

    @PostConstruct
    private void init() {

        this.poolCore = Runtime.getRuntime().availableProcessors();
        if (this.poolCore <= 8) {
            this.poolCore = 16;
        }

        log.info("[{}] ----------------------------", getClass().getSimpleName());
        log.info("[{}]  availableProcessors: {} EA", getClass().getSimpleName(), Runtime.getRuntime().availableProcessors());
        log.info("[{}]             PoolCore: {} EA", getClass().getSimpleName(), this.poolCore);
    }

    public ThreadPoolTaskExecutor getDefaultExecutor(int poolSize) {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
        threadPoolTaskExecutor.setCorePoolSize(poolSize);           // 인스턴스 되면서 기본적으로 띄울 스레드 개수.
                                                                    // 아무작업이 없어도 corePoolSize 만큼 스레드가 생성
        threadPoolTaskExecutor.setMaxPoolSize(poolSize*2);          // 풀 최대개수, Queue Capacity 까지 꽉차는 경우 maxPoolSize 만큼 넓혀감
        threadPoolTaskExecutor.setQueueCapacity(poolSize*4);        // 스레드 대기큐, Queue Capacity 가 꽉차면 스레드가 추가로 생성됨. Async 처리시 Queue Size
                                                                    // (설정하지 않으면 Integer.MAX 이기 때문에 성능에 문제가 발생함)
        return threadPoolTaskExecutor;
    }

    @Bean(name="cctvPsetScnrExecutor")
    public Executor getCctvPsetScnrExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = getDefaultExecutor(this.poolCore);
        threadPoolTaskExecutor.setThreadNamePrefix("pset-scnr-pool-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
    @Bean(name="centerCommExecutor")
    public Executor getCenterCommExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = this.getDefaultExecutor((int)(this.poolCore/2));
        threadPoolTaskExecutor.setThreadNamePrefix("udp-comm-pool-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Bean(name="schJobExecutor")
    public Executor getSchJobExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = getDefaultExecutor(this.poolCore);
        threadPoolTaskExecutor.setThreadNamePrefix("sch-job-pool-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPoolTaskExecutor = getDefaultExecutor(this.poolCore *2);
        threadPoolTaskExecutor.setThreadNamePrefix("async-pool-");
        threadPoolTaskExecutor.initialize();
        return threadPoolTaskExecutor;
    }
}
