/**
 * All rights Reserved, Designed By www.freemud.cn
 *
 * @Title: ApiApplication
 * @Package cn.freemud
 * @Description:
 * @author: xudong.cai
 * @date: 2018/5/4 10:45
 * @version V1.0
 * @Copyright: 2018 www.freemud.cn Inc. All rights reserved.
 * 注意：本内容仅限于上海非码科技内部传阅，禁止外泄以及用于其他的商业目
 */
package cn.freemud;

import cn.freemud.core.db.DataSourcesConfig;
import com.alibaba.fastjson.parser.ParserConfig;
import com.freemud.application.sdk.api.couponcenter.config.CouponRestTemplateConfig;
import com.freemud.application.sdk.api.log.LogThreadLocal;
import feign.RequestInterceptor;
import org.apache.commons.lang.StringUtils;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.*;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import tk.mybatis.spring.annotation.MapperScan;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@ServletComponentScan
@ImportAutoConfiguration(classes = {DataSourcesConfig.class})
@EnableSwagger2
@EnableCircuitBreaker
@SpringBootApplication @EnableDiscoveryClient
@EnableAspectJAutoProxy
@ComponentScan(value = {"cn.freemud", "com.freemud"},excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
        classes ={ CouponRestTemplateConfig.RestTemplateConfig.class})})
@MapperScan({"cn.freemud.*.dao","com.freemud.sdk.api.assortment.orderdistributor.mapper","com.freemud.api.assortment.datamanager.manager",
                "com.freemud.api.assortment.datamanager.queue.dao","com.freemud.api.assortment.datamanager.rbac.dao","com.freemud.api.assortment.datamanager.queue.entity"})
@EnableFeignClients({"cn.freemud.service.thirdparty",
        "com.freemud.sdk.api.assortment.message",
        "cn.freemud.service.mccafe.thirdparty",
        "cn.freemud.management.thirdparty",
        "cn.freemud.fuyou"
})
@EnableAutoConfiguration
@EnableScheduling
public class OrderApplication {

    private static final String GRAY_VERSION_PROD = "PROD"; //生产版本
    private static final String GRAY_VERSION_GRAY = "GRAY"; //灰度版本

    public static void main(String[] args) {
        String getenv = System.getenv("VERSION_FLAG");
        System.setProperty("eureka.instance.metadataMap.version", StringUtils.isEmpty(getenv) ? GRAY_VERSION_PROD : GRAY_VERSION_GRAY.equals(getenv) ? GRAY_VERSION_GRAY : GRAY_VERSION_PROD);
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
        SpringApplication.run(OrderApplication.class, args);
    }

    @Bean("jasyptStringEncryptorFreemud")
    public StringEncryptor stringEncryptor() {
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("configDbkey");
        config.setAlgorithm("PBEWithMD5AndDES");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);
        return encryptor;
    }

    /**
     * 定义feign-client 带上x-transaction-id
     *
     * @return
     */
    @Bean
    public RequestInterceptor headerInterceptor() {
        return requestTemplate -> requestTemplate.header("x-tranaction-id", LogThreadLocal.getTrackingNo());
    }

    @EnableAsync
    @Configuration
    class TaskPoolConfig {

        @Bean("couponExecutor")
        public Executor taskExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(8);
            executor.setMaxPoolSize(10);
            executor.setQueueCapacity(20000);
            executor.setKeepAliveSeconds(60);
            executor.setThreadNamePrefix("CouponExecutor-");
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }
        @Bean("mcCafePushOrderExecutor")
        public Executor mcCafePushOrderExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(1);
            executor.setMaxPoolSize(1);
            executor.setKeepAliveSeconds(60);
            executor.setQueueCapacity(100);
            executor.setWaitForTasksToCompleteOnShutdown(true);
            executor.setAwaitTerminationSeconds(60);
            executor.setThreadNamePrefix("mcCafePushOrderExecutor-");
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }

        @Bean("mcCafePushOrderSubExecutor")
        public Executor mcCafePushOrderSubExecutor() {
            ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
            executor.setCorePoolSize(8);
            executor.setMaxPoolSize(16);
            executor.setKeepAliveSeconds(60);
            executor.setQueueCapacity(100);
            executor.setWaitForTasksToCompleteOnShutdown(true);
            executor.setAwaitTerminationSeconds(60);
            executor.setThreadNamePrefix("mcCafePushOrderSubExecutor-");
            executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
            return executor;
        }
    }
}
