/**
 * 
 */
package org.springblade.datasource.support;

import com.alibaba.druid.util.JdbcUtils;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.druid.DruidConfig;
import com.baomidou.dynamic.datasource.creator.druid.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.exception.ServiceException;
import org.springblade.datasource.enums.DsTypeEnum;
import org.springblade.etl.entity.bi.ReportDatasource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * @author wookvn
 *
 */
@Slf4j
@Component
public class DynamicDataSourceSupport {

	@Autowired
	private DynamicRoutingDataSource dynamicRoutingDataSource;

	@Autowired
	private DruidDataSourceCreator dataSourceCreator;
	
	@Autowired
	private DynamicDataSourceProperties dynamicDataSourceProperties;

	/**
	 * 添加数据源
	 * 
	 * @param ds
	 * @return
	 */
	public boolean addDs(ReportDatasource ds) {
		try {
			if (DynamicDataSourceSupport.testDs(ds)) {
				DataSourceProperty dataSourceProperty = new DataSourceProperty();
				dataSourceProperty.setPoolName(ds.getPoolName());
				dataSourceProperty.setUrl(ds.getUrl());
				dataSourceProperty.setUsername(ds.getDsUser());
				dataSourceProperty.setPassword(ds.getDsPassword());
				dataSourceProperty.setDriverClassName(ds.getDriverClassName());
				//设置数据源连接属性
				dataSourceProperty.setDruid(DynamicDataSourceSupport.customConnectionConfig(dynamicDataSourceProperties.getDruid(), ds));
				DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
				dynamicRoutingDataSource.addDataSource(ds.getPoolName(), dataSource);
				return true;
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			throw new ServiceException("数据源连接失败");
		}
		return false;
	}

	/**
	 * 移除数据源
	 * 
	 * @param ds
	 * @return
	 */
	public boolean removeDs(String poolName) throws Exception {
		dynamicRoutingDataSource.removeDataSource(poolName);
		return true;
	}

	/**
	 * 获取所有数据源
	 * 
	 * @return List<poolName>
	 */
	public List<String> getAllDs() {
		List<String> dsList = new ArrayList<String>();
		Map<String, DataSource> dataSources = dynamicRoutingDataSource.getDataSources();
		if (dataSources != null && !dataSources.isEmpty()) {
			for (Map.Entry<String, DataSource> entry : dataSources.entrySet()) {
				dsList.add(entry.getKey());
			}
		}
		return dsList;
	}
	
	/**
	 * 
	 * @param poolName
	 * @return
	 */
	public boolean exists(String poolName) {
		List<String> dsList = getAllDs();
		return dsList != null ? dsList.contains(poolName) : false;
	}

	/**
	 * 测试数据源
	 * 
	 * @param ds
	 * @return
	 */
	public static boolean testDs(ReportDatasource ds) {
		Connection connection = null;
		Statement statement = null;
		try {
			connection = DynamicDataSourceSupport.createConnection(ds);
			statement = connection.createStatement();
			statement.executeQuery(ds.getDsTypeSyl().getValidationQuery());
			return true;
		} catch (Exception e) {
			log.error(e.getMessage());
		} finally {
			JdbcUtils.close(connection);
			JdbcUtils.close(statement);
		}
		return false;
	}
	
	/**
	 * 
	 * @param ds
	 * @return
	 * @throws Exception
	 */
	public static Connection createConnection(ReportDatasource ds) throws Exception {
		return createConnection(ds, false);
	}
	
	/**
	 * 创建连接
	 * @param ds
	 * @return
	 * @throws SQLException
	 */
	public static Connection createConnection(ReportDatasource ds, boolean heavyCall) throws Exception {
		Properties props = new Properties();
		props.put("user", ds.getDsUser());
		props.put("password", ds.getDsPassword());
		//用于显示字段注释
		props.put("remarks", "true");
//		props.put("useInformationSchema", "true");
		props.put("remarksReporting", "true");
		props.put("nullCatalogMeansCurrent", "true");
		//获取每个数据库的超时时间
		Map<String, String> timeoutMap = ds.getDsTypeSyl().jdbcConnectionPropTimeout(heavyCall);
		if(timeoutMap == null) {
			throw new ServiceException(String.format("数据库[%s]未设置超时时间，请先设置", ds.getDsTypeSyl().name()));
		}
		props.putAll(timeoutMap);
		if(ds.getDsTypeSyl() == DsTypeEnum.xugu) {
			Class.forName("com.xugu.cloudjdbc.Driver");
		}
		return DriverManager.getConnection(ds.getUrl(), props);
	}
	
	/**
	 * 初始化jdbc连接配置
	 * @param druidConfig
	 * @param reportDs
	 * @return
	 */
	public static DruidConfig customConnectionConfig(DruidConfig druidConfig, ReportDatasource reportDs) {
		return null;
	}
}
