package cn.feast.coding.tools;

import cn.feast.coding.model.generator.Colunm;
import cn.feast.coding.model.generator.DataSource;
import cn.feast.coding.model.generator.Table;
import com.alibaba.druid.pool.DruidDataSource;
import org.apache.commons.lang.StringUtils;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

public class AlibabaDbConnect {
    private static DruidDataSource dataSource = null;

    /**
     * 构造函数完成数据库的连接和连接对象的生成
     *
     * @throws Exception
     */
    public AlibabaDbConnect() {

    }

    public static void GetDbConnect(DataSource data) throws Exception {
        try {
            if (dataSource == null) {
                dataSource = new DruidDataSource();
                //设置连接参数
                dataSource.setUrl(data.getJdbcUrl());
                dataSource.setDriverClassName("com.mysql.jdbc.Driver");
                dataSource.setUsername(data.getJdbcUser());
                dataSource.setPassword(data.getJdbcPass());
                //配置初始化大小、最小、最大
                dataSource.setInitialSize(1);
                dataSource.setMinIdle(1);
                dataSource.setMaxActive(20);
                //连接泄漏监测
                dataSource.setRemoveAbandoned(true);
                dataSource.setRemoveAbandonedTimeout(30);
                //配置获取连接等待超时的时间
                dataSource.setMaxWait(20000);
                //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
                dataSource.setTimeBetweenEvictionRunsMillis(20000);
                //防止过期
                dataSource.setValidationQuery("SELECT 'x'");
                dataSource.setTestWhileIdle(true);
                dataSource.setTestOnBorrow(true);
            }
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * 获取数据库所有数据表名称
     *
     * @param dataSource
     * @return
     */
    public static List<Table> getTables(DataSource dataSource) {
        List<Table> tables = new ArrayList<Table>();
        Table table = null;
        Connection conn = null;
        ResultSet rs = null;
        try {
            conn = getConnect(dataSource);
            DatabaseMetaData dbMetaData = conn.getMetaData();
            rs = dbMetaData.getTables(null, null, null, new String[]{"TABLE"});
            while (rs.next()) {
                table = new Table();
                String tableName = rs.getString("TABLE_NAME");
                table.setTableName(tableName);
                table.setClassName(getClassName(tableName));
                tables.add(table);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tables;
    }

    /**
     * 读取表数据
     *
     * @param dataSource 数据源
     * @param tableName  表名
     * @return
     */
    public static List<Colunm> readData(DataSource dataSource,
                                        String tableName) {
        List<Colunm> properties = new ArrayList<Colunm>();
        Colunm colunm = null;
        Connection conn = null;
        ResultSet rs = null;
        String primaryKey = genFieldName(getPrimaryKey(dataSource, tableName));
        try {
            conn = getConnect(dataSource);
            DatabaseMetaData dbmd = conn.getMetaData();
            rs = dbmd.getColumns(null, null, tableName, null);
            while (rs.next()) {
                colunm = new Colunm();
                String colunmName = genFieldName(rs.getString("COLUMN_NAME"));
                colunm.setColunmName(colunmName);
                colunm.setFiledName(rs.getString("COLUMN_NAME"));
                if (colunmName.equals(primaryKey)) {
                    colunm.setIsPrimary(1);
                } else {
                    colunm.setIsPrimary(0);
                }
                int dataType = rs.getInt("DATA_TYPE"); //对应的java.sql.Types类型
                int columnSize = rs.getInt("COLUMN_SIZE");//列大小
                int decimalDigits = rs.getInt("DECIMAL_DIGITS");//小数位数
                colunm.setColunmType(JavaType.getType(dataType, columnSize, decimalDigits));
                colunm.setShowName(rs.getString("REMARKS"));
                properties.add(colunm);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return properties;
    }

    /**
     * 获取数据表主键
     *
     * @param dataSource
     * @param tableName
     * @return
     */
    public static String getPrimaryKey(DataSource dataSource, String tableName) {
        Connection conn = null;
        ResultSet rs = null;
        String primaryKeyName = "";
        try {
            conn = getConnect(dataSource);
            rs = conn.getMetaData().getPrimaryKeys(null, null, tableName);
            if (rs.next()) {
                primaryKeyName = rs.getString(4);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (StringUtils.isNotEmpty(primaryKeyName)) {
            return primaryKeyName;
        } else {
            return null;
        }
    }

    /**
     * 根据表字段名获取java中的字段名
     *
     * @param field 字段名
     * @return
     */
    public static String genFieldName(String field) {
        //处理字段名忽视部分
        String[] ignore = Contants.FILED_IGNORE;
        for (int i = 0; i < ignore.length; i++) {
            if (field.contains(ignore[i])) {
                field = field.replace(ignore[i], "");
            }
        }
        //处理字段名
        String result = "";
        if (field.contains("_")) {
            String lowerFeild = field.toLowerCase();
            String[] fields = lowerFeild.split("_");
            result += fields[0];
            if (fields.length > 1) {
                for (int i = 1; i < fields.length; i++) {
                    result += fields[i].substring(0, 1).toUpperCase() + fields[i].substring(1, fields[i].length());
                }
            }
        } else {
            result = field;
        }
        return result;
    }

    /**
     * 根据表名获取类名
     *
     * @param tableName 表名
     * @return
     */
    public static String getClassName(String tableName) {
        String result = "";
        String lowerFeild = tableName.toLowerCase();
        //处理表名
        String[] ignore = Contants.TABLE_IGNORE;
        for (int i = 0; i < ignore.length; i++) {
            if (lowerFeild.contains(ignore[i])) {
                lowerFeild = lowerFeild.replace(ignore[i], "");
            }
        }
        String[] fields = lowerFeild.split("_");
        if (fields.length >= 1) {
            for (int i = 0; i < fields.length; i++) {
                result += fields[i].substring(0, 1).toUpperCase() + fields[i].substring(1, fields[i].length());
            }
        }
        return result;
    }
    /**
     * 取得已经构造生成的数据库连接
     *
     * @return 返回数据库连接对象
     * @throws Exception
     */
    public static Connection getConnect(DataSource data) throws Exception {
        Connection con = null;
        try {
            GetDbConnect(data);
            con = dataSource.getConnection();
        } catch (Exception e) {
            throw e;
        }
        return con;
    }
}
