package com.chenyang.nse.bussiness.bean;

import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.service.core.impl.DataSystemServiceImpl;
import com.chenyang.nse.bussiness.tools.jdbc.JdbcTool;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

public class CacheHiveTDH implements Runnable {
   public static final int SCHEMA_BATCH_SIZE = 1;
   public static final int TABLE_BATCH_SIZE = 1000;
   public static final int PAGE_SIZE = 50000;
   private DataSystemServiceImpl dataSystemService;
   private TCoreDatasystem datasystem;
   private CountDownLatch cdl;

   public CacheHiveTDH(DataSystemServiceImpl dataSystemService, TCoreDatasystem datasystem, CountDownLatch cdl) {
      this.dataSystemService = dataSystemService;
      this.datasystem = datasystem;
      this.cdl = cdl;
   }

   public void run() {
      Connection connection = null;
      Statement statement = null;
      Connection connection2 = null;
      Statement statement2 = null;

      try {
         DataBase dataBase = new DataBase();
         dataBase.setDatasystemid(this.datasystem.getId());
         dataBase.setDbType(this.datasystem.getDbtype());
         dataBase.setIp_port(this.datasystem.getDbip() + ":" + this.datasystem.getDbport());
         boolean exist = false;

         for(DataBase base : DataCache.dataList) {
            if (base.getDatasystemid().equals(this.datasystem.getId())) {
               exist = true;
               dataBase = base;
               break;
            }
         }

         if (!exist) {
            DataCache.dataList.add(dataBase);
         }

         connection = this.dataSystemService.getConnection(this.datasystem.getId());
         statement = connection.createStatement();
         long totalStart = System.currentTimeMillis();
         List<Schema> schemaList = this.getSchema(statement);
         int schemaSize = schemaList.size();
         int loop = (int)Math.ceil((double)1.0F * (double)schemaSize / (double)1.0F);
         List<List<Schema>> schemaSubs = new ArrayList();

         for(int i = 0; i < loop; ++i) {
            int fromIndex = i * 1;
            int toIndex = (i + 1) * 1;
            if (fromIndex > schemaSize) {
               fromIndex = schemaSize;
            }

            if (toIndex > schemaSize) {
               toIndex = schemaSize;
            }

            List<Schema> schemaSub = schemaList.subList(fromIndex, toIndex);
            schemaSubs.add(schemaSub);
         }

         connection2 = this.dataSystemService.getConnection(this.datasystem.getId());
         statement2 = connection2.createStatement();
         Statement finalStatement = statement2;
         schemaSubs.stream().forEach((item) -> {
            try {
               this.cacheSchema(finalStatement, item);
            } catch (SQLException throwables) {
               throwables.printStackTrace();
            }

         });
         dataBase.setSchemaList(schemaList);
         dataBase.easyCache = new DBEasyCache(dataBase);
         dataBase.easyCache.init();
      } catch (Throwable e) {
         e.printStackTrace();
      } finally {
         try {
            JdbcTool.closeConnection(connection);
            if (statement != null) {
               statement.close();
            }

            JdbcTool.closeConnection(connection2);
            if (statement2 != null) {
               statement2.close();
            }
         } catch (SQLException throwables) {
            throwables.printStackTrace();
         }

         this.cdl.countDown();
         System.out.println("hiveTDH结束缓存");
      }

   }

   public List<Schema> getSchema(Statement statement) throws SQLException {
      List<Schema> schemas = new ArrayList();
      String sql = "show databases";
      ResultSet resultSet = statement.executeQuery(sql);

      while(resultSet.next()) {
         Schema schema = new Schema(resultSet.getString("DATABASE_NAME"));
         schemas.add(schema);
      }

      resultSet.close();
      return schemas;
   }

   private void cacheSchema(Statement statement, List<Schema> schemaSub) throws SQLException {
      List<Table> tableList = new ArrayList();
      List<Column> columns = new ArrayList();
      long start1 = System.currentTimeMillis();
      List<Table> tableListTemp = this.getTables(statement, schemaSub);
      tableList.addAll(tableListTemp);
      int tableSize = tableListTemp.size();
      int loop = (int)Math.ceil((double)1.0F * (double)tableSize / (double)1000.0F);

      for(int j = 0; j < loop; ++j) {
         int fromIndexTable = j * 1000;
         int toIndexTable = (j + 1) * 1000;
         if (fromIndexTable > tableSize) {
            fromIndexTable = tableSize;
         }

         if (toIndexTable > tableSize) {
            toIndexTable = tableSize;
         }

         List<Table> tableSub = tableList.subList(fromIndexTable, toIndexTable);
         long start3 = System.currentTimeMillis();
         List<Column> columnsTemp = this.getColumns(statement, schemaSub, tableSub);
         columns.addAll(columnsTemp);
         long e = System.currentTimeMillis();
      }

      long start5 = System.currentTimeMillis();
      Map<String, Schema> schemasMap = new HashMap();
      Map<String, Table> tablesMap = new HashMap();

      for(Schema schema : schemaSub) {
         schemasMap.put(schema.getName(), schema);
      }

      for(Table table : tableList) {
         String key = this.getSchemaTableId(table.getSchema(), table.getName());
         tablesMap.put(key, table);
         ((Schema)schemasMap.get(table.getSchema())).getTableList().add(table);
      }

      for(Column column : columns) {
         String key = this.getSchemaTableId(column.getSchema(), column.getTable());

         try {
            ((Table)tablesMap.get(key)).getColumnList().add(column);
         } catch (Exception var19) {
            System.out.println(key);
         }
      }

      long end1 = System.currentTimeMillis();
      System.out.println("hiveTDH schema:" + tableSize + " tables 用时:" + (end1 - start1) / 1000L);
   }

   public String getSchemaTableId(String schemaName, String tableName) {
      return schemaName + "--->" + tableName;
   }

   private List<Table> getTables(Statement statement, List<Schema> schemas) throws SQLException {
      String schemasWhere = String.join("','", (Iterable)schemas.stream().filter((x) -> x != null && x.getName().length() > 0).map((x) -> x.getName()).collect(Collectors.toList()));
      List<Table> tables = new ArrayList();
      int pageNum = 1;
      int pageSize = 50000;

      while(true) {
         int offset = (pageNum - 1) * pageSize;
         String sql = "SELECT database_name, table_name FROM SYSTEM.tables_v WHERE database_name in ('" + schemasWhere + "') limit " + offset + " ,  " + pageSize;
         ResultSet resultSet = statement.executeQuery(sql);

         while(resultSet.next()) {
            String schema = resultSet.getString("database_name");
            Table table = new Table(resultSet.getString("table_name"), schema);
            tables.add(table);
         }

         if (resultSet.getRow() < pageSize) {
            return tables;
         }

         resultSet.close();
         ++pageNum;
      }
   }

   private List<Column> getColumns(Statement statement, List<Schema> schemas, List<Table> tables) throws SQLException {
      int pageNum = 1;
      int pageSize = 50000;
      String schemasWhere = String.join("','", (Iterable)schemas.stream().filter((x) -> x != null && x.getName().length() > 0).map((x) -> x.getName()).collect(Collectors.toList()));
      String tablesWhere = String.join("','", (Iterable)tables.stream().filter((x) -> x != null && x.getName().length() > 0).map((x) -> x.getName()).collect(Collectors.toList()));
      List<Column> columns = new ArrayList(50000);

      while(true) {
         int offset = (pageNum - 1) * pageSize;
         String sql = "SELECT column_id, column_name, column_type, table_name, database_name, commentstring, default_value, nullable, unique_constraint, column_length, column_scale  FROM SYSTEM.columns_v where database_name in( '" + schemasWhere + "') and table_name in ('" + tablesWhere + "')  ORDER BY column_id limit " + offset + " ,  " + pageSize;
         ResultSet resultSet = statement.executeQuery(sql);
         resultSet.setFetchSize(50000);
         Column column = null;

         while(resultSet.next()) {
            column = new Column();
            String schema = resultSet.getString("database_name");
            String table = resultSet.getString("table_name");
            column.setColumnName(resultSet.getString("column_name"));
            column.setSchema(schema);
            column.setTable(table);
            Object scale = resultSet.getObject("column_scale");
            String remark = resultSet.getString("commentstring");
            columns.add(column);
         }

         if (resultSet.getRow() < pageSize) {
            return columns;
         }

         resultSet.close();
         ++pageNum;
      }
   }
}
