package com.ruoyi.framework.datasource;

import com.alibaba.druid.pool.DruidDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.util.CollectionUtils;

import javax.sql.DataSource;
import java.sql.DriverManager;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 动态数据源
 *
 * @author ruoyi
 */
@Slf4j
public class DynamicDataSource extends AbstractRoutingDataSource {
    private final Map<Object, Object> targetDataSourceMap;

    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
        this.targetDataSourceMap = targetDataSources;
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }

    public boolean createDataSource(List<DruidDataSource> dataSources) {
        if (!CollectionUtils.isEmpty(dataSources)) return false;
        for (DruidDataSource ds : dataSources) {
            try {
                Class.forName(ds.getDriverClassName());
                DriverManager.getConnection(ds.getUrl(), ds.getUsername(), ds.getPassword());
                //申请连接时执行validationQuery检测连接是否有效，这里建议配置为TRUE，防止取到的连接不可用
                ds.setTestOnBorrow(true);
                //建议配置为true，不影响性能，并且保证安全性。
                ds.setTestWhileIdle(true);
                //申请连接的时候检测，如果空闲时间大于timeBetweenEvictionRunsMillis，执行validationQuery检测连接是否有效。
                ds.setValidationQuery("select 1 ");
                ds.init();
                this.targetDataSourceMap.put(ds.getName(), ds);
            } catch (Exception e) {
                log.error(e.getMessage());
            }
        }
        super.setTargetDataSources(this.targetDataSourceMap);
        super.afterPropertiesSet();
        return true;
    }

    public boolean existsDataSource(String key) {
        return Objects.nonNull(this.targetDataSourceMap.get(key));
    }
}