package net.northking.cctp.maven.analyse.dialects;

import net.northking.cctp.maven.analyse.Constants;
import net.northking.cctp.maven.analyse.Messages;
import net.northking.cctp.maven.analyse.entity.TableRef;
import net.northking.cctp.maven.analyse.util.DBUtil;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MySql数据库方言
 *
 * @author 谢秀松
 * @since 1.0
 */
public final class MySQLDialect extends AbsDialect
{
  /**
   * 是否执行过“加载表结构”
   */
  private static boolean exec = false;

  /**
   * 单例模式：mysql数据库方言实例
   */
  private static MySQLDialect instance = new MySQLDialect();

  /**
   * 单例模式：隐藏构造函数
   */
  private MySQLDialect()
  {
  }

  /**
   * 获取MySql方言实例
   *
   * @return MySql方言实例
   */
  public static MySQLDialect getInstance()
  {
    return instance;
  }

  /**
   * 表注释Map
   */
  private Map<String, String> tableCommentMap = new HashMap<>();

  /**
   * 获取表的注释
   *
   * @throws ClassNotFoundException ClassNotFoundException
   * @throws SQLException           SQLException
   * @throws InstantiationException InstantiationException
   * @throws IllegalAccessException IllegalAccessException
   */
  private void loadTablesComment(String[] tableNames)
      throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException
  {

    StringBuilder sql = new StringBuilder("");
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    Connection conn = null;
    try
    {
      conn = DBUtil.getInstance().getConnection();

      sql.append("select t.TABLE_NAME,t.TABLE_COMMENT from information_schema.TABLES t ");
      sql.append(" where t.TABLE_SCHEMA = '").append(conn.getCatalog()).append("'");

      if (tableNames != null && tableNames.length > 0)
      {
        StringBuilder subSql = new StringBuilder("");
        for (String tableName : tableNames)
        {
          subSql.append(",'").append(tableName).append("'");
        }
        sql.append(" and t.TABLE_NAME in (").append(subSql.substring(1)).append(")");
      }

      Messages.debug("Print.SQL", sql.toString());
      pstmt = conn.prepareStatement(sql.toString());
      rs = pstmt.executeQuery();
      while (rs.next())
      {
        String tableName = rs.getString(Constants.TABLE_NAME);
        String tableComment = rs.getString(Constants.TABLE_COMMENT);
        tableCommentMap.put(tableName, tableComment);
      }

      StringBuilder useDatabase = new StringBuilder("use ");
      useDatabase.append(conn.getCatalog());
      Messages.debug("Print.SQL", useDatabase.toString());
      pstmt.execute(useDatabase.toString());
    } finally
    {
      if (rs != null)
      {
        rs.close();
        pstmt.close();
      }
      if (conn != null){
        conn.close();
      }
    }
  }

  /**
   * 获取表的注释
   *
   * @param resultSet 结果集
   * @return 表的注释
   * @throws SQLException
   */
  protected String findTableComment(ResultSet resultSet) throws SQLException
  {
    String tableName = resultSet.getString(Constants.TABLE_NAME);
    String tableComment = tableCommentMap.get(tableName);
    if (tableComment == null)
    {
      tableComment = "";
    }
    return tableComment;
  }

  /**
   * 加载表结构
   *
   * @return 表结构
   * @throws Exception Exception
   */
  public List<TableRef> loadTables(String schema, String[] tableNames) throws Exception
  {
    loadTablesComment(tableNames);
    loadTable(schema, tableNames);
    analyseTables();
    exec = true;
    return tables;
  }

  /**
   * 获取表结构
   *
   * @return 表结构
   * @throws Exception Exception
   */
  public List<TableRef> getTables(String schema, String[] tableNames) throws Exception
  {
    if (exec)
    {
      return tables;
    } else
    {
      return loadTables(schema, tableNames);
    }
  }

}
