package com.pcloud.common.core.datasource;

import java.sql.SQLException;
import java.util.ArrayList;

import javax.sql.DataSource;

import com.pcloud.common.core.mybatis.interceptor.ExecutorInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.boot.autoconfigure.SpringBootVFS;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration
@MapperScan(basePackages = DataSourceConfig.PACKAGE,sqlSessionFactoryRef = "sqlSessionFactory")
public class DataSourceConfig {
    private Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);

    static final String PACKAGE = "com.pcloud.common.core.dao";

    @Value("${spring.datasource.url}")
    private String dbUrl;

    @Value("${spring.datasource.type}")
    private String dbType;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    @Value("${spring.datasource.driver-class-name}")
    private String driverClassName;

    @Value("${spring.datasource.initialSize}")
    private int initialSize;

    @Value("${spring.datasource.minIdle}")
    private int minIdle;

    @Value("${spring.datasource.maxActive}")
    private int maxActive;

    @Value("${spring.datasource.maxWait}")
    private int maxWait;

    @Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.validationQuery}")
    private String validationQuery;

    @Value("${spring.datasource.testWhileIdle}")
    private boolean testWhileIdle;

    @Value("${spring.datasource.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.testOnReturn}")
    private boolean testOnReturn;

    @Value("${spring.datasource.poolPreparedStatements}")
    private boolean poolPreparedStatements;

    @Value("${spring.datasource.filters}")
    private String filters;

    @Value("${spring.datasource.connectionProperties}")
    private String connectionProperties;

    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;

    @Value("${mybatis.type-aliases-package}")
    private String typeAliasesPackage;

//    @Value("${spring.datasource.useGlobalDataSourceStat}")
//    private boolean useGlobalDataSourceStat;
//
//    @Value("${spring.datasource.druidLoginName}")
//    private String druidLoginName;
//
//    @Value("${spring.datasource.druidPassword}")
//    private String druidPassword;

    @Bean(name="druidDataSource")
    @Primary //不要漏了这
    public DataSource dataSource(){
        DruidDataSource datasource = new DruidDataSource();
        try {
            datasource.setUrl(this.dbUrl);
            datasource.setDbType(dbType);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);
            datasource.setInitialSize(initialSize);
            datasource.setMinIdle(minIdle);
            datasource.setMaxActive(maxActive);
            datasource.setMaxWait(maxWait);
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            datasource.setValidationQuery(validationQuery);
            datasource.setTestWhileIdle(testWhileIdle);
            datasource.setTestOnBorrow(testOnBorrow);
            datasource.setTestOnReturn(testOnReturn);
            datasource.setPoolPreparedStatements(poolPreparedStatements);
            datasource.setFilters(filters);
            datasource.setConnectionProperties(connectionProperties);
//            datasource.setUseGlobalDataSourceStat(useGlobalDataSourceStat);
            ArrayList<String> arr = new ArrayList<>();
            arr.add("set names utf8mb4;");
            datasource.setConnectionInitSqls(arr);
        } catch (SQLException e) {
            logger.error("druid configuration initialization filter", e);
        }
        return datasource;
    }

    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager() {
        logger.info("【DataSource】初始化TransactionManager事务管理器，<START>");
        return new DataSourceTransactionManager(dataSource());
    }


    @Bean(name = "sqlSessionFactory")
    @Autowired
    public SqlSessionFactory sqlSessionFactory(ExecutorInterceptor interceptor) throws Exception {
        logger.info("【DataSource】初始化SqlSessionFactory，<START>");
        final SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
        sessionFactoryBean.setDataSource(dataSource());
        sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        sessionFactoryBean.setVfs(SpringBootVFS.class);
        sessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
        sessionFactoryBean.setPlugins(new Interceptor[]{interceptor});
        return sessionFactoryBean.getObject();
    }

    @Bean(name = "sqlSessionTemplate")
    @Autowired
    public SqlSessionTemplate sqlSessionTemplate(ExecutorInterceptor interceptor) throws Exception {
        logger.info("【DataSource】初始化SqlSessionTemplate，<START>");
        final SqlSessionTemplate sessionFactoryBean = new SqlSessionTemplate(sqlSessionFactory(interceptor));
        return sessionFactoryBean;
    }
}
