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 org.apache.commons.lang.StringUtils;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

public class DataBaseTools {
    /**
     * 获取数据库所有数据表名称
     *
     * @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 = getConn(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();
        } finally {
            closeConn(rs, null, conn);
        }
        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 = getConn(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();
        } finally {
            closeConn(rs, null, conn);
        }
        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 = getConn(dataSource);
            rs = conn.getMetaData().getPrimaryKeys(null, null, tableName);
            if (rs.next()) {
                primaryKeyName = rs.getString(4);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeConn(rs, null, conn);
        }

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

    /**
     * 根据表字段名获取java中的字段名
     *
     * @param field 字段名
     * @return
     */
    public static String genFieldName(String field) {
        if(StringUtils.isEmpty(field)){
            return "";
        }
        //处理字段名忽视部分
        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;
    }

    /**
     * 获取数据库连接
     *
     * @param dataSource
     * @return
     */
    public static Connection getConn(DataSource dataSource) {
        Connection conn = null;
        try {
            Class.forName("com.mysql.jdbc.Driver");
            conn = DriverManager.getConnection(dataSource.getJdbcUrl(), dataSource.getJdbcUser(), dataSource.getJdbcPass());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    /**
     * 关闭数据库连接
     *
     * @param rs
     * @param stm
     * @param conn
     */
    public static void closeConn(ResultSet rs, Statement stm, Connection conn) {
        try {
            if (rs != null)
                rs.close();
            if (stm != null)
                stm.close();
            if (conn != null)
                conn.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试数据库连接
     *
     * @param dataSource
     * @return
     */
    public static int testConnection(DataSource dataSource) {
        Connection conn = null;
        ResultSet rs = null;
        Statement st = null;
        int data = 0;
        String sql = "select 1";
        try {
            conn = getConn(dataSource);
            st = conn.createStatement();
            rs = st.executeQuery(sql);
            if (rs.next()) {
                data = rs.getInt(1);
            }
        } catch (Exception e) {
            return data;
        } finally {
            closeConn(rs, st, conn);
        }
        return data;
    }
}
