package com.chenyang.nse.bussiness.tools.jdbc;

import com.chenyang.nse.bussiness.bean.Column;
import com.chenyang.nse.bussiness.bean.DataBase;
import com.chenyang.nse.bussiness.bean.DataCache;
import com.chenyang.nse.bussiness.bean.Schema;
import com.chenyang.nse.bussiness.bean.Table;
import com.chenyang.nse.bussiness.entity.db.ColumnInfo;
import com.chenyang.nse.bussiness.entity.orm.table.core.TCoreDatasystem;
import com.chenyang.nse.bussiness.tools.string.AesTool;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.ListIndexesIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.UpdateResult;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.bson.Document;
import org.bson.conversions.Bson;

public class MongodbTool {
   public static MongoClient connect(String databaseName, String username, String passwd, String ip, int port, boolean auth) throws Exception {
      MongoClient client = null;
      if (auth) {
         MongoCredential credential = MongoCredential.createCredential(username, databaseName, passwd.toCharArray());
         ServerAddress addr = new ServerAddress(ip, port);
         client = new MongoClient(addr, Arrays.asList(credential));
      } else {
         client = new MongoClient(ip, port);
      }

      return client;
   }

   public static void closeClient(MongoClient client) {
      if (client != null) {
         client.close();
      }

   }

   public static void insert(MongoCollection<Document> collection, Document document) {
      collection.insertOne(document);
   }

   public static List<Document> findAll(MongoCollection<Document> collection) {
      List<Document> results = new ArrayList();
      FindIterable<Document> iterables = collection.find();
      MongoCursor<Document> cursor = iterables.iterator();

      while(cursor.hasNext()) {
         results.add(cursor.next());
      }

      return results;
   }

   public static List<Document> findBy(MongoCollection<Document> collection, Bson filter) {
      List<Document> results = new ArrayList();
      FindIterable<Document> iterables = collection.find(filter);
      MongoCursor<Document> cursor = iterables.iterator();

      while(cursor.hasNext()) {
         results.add(cursor.next());
      }

      return results;
   }

   public static Map<String, String> findAll(MongoClient client, String schema, String collectionName) throws Exception {
      Map<String, String> map = new HashMap();
      StringBuffer sb1 = new StringBuffer();
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      MongoCollection<Document> collection = db.getCollection(collectionName);

      for(Document doc : findAll(collection)) {
         int i = 0;
         sb1.append(doc.toJson());
         sb1.append(",");
      }

      map.put("content", sb1.toString());
      return map;
   }

   public static UpdateResult updateOne(MongoCollection<Document> collection, Bson filter, Bson update) {
      UpdateResult result = collection.updateOne(filter, update);
      return result;
   }

   public static UpdateResult updateMany(MongoCollection<Document> collection, Bson filter, Bson update) {
      UpdateResult result = collection.updateMany(filter, update);
      return result;
   }

   public static void replace(MongoCollection<Document> collection, Bson filter, Document replacement) {
      collection.replaceOne(filter, replacement);
   }

   public static void deleteOne(MongoCollection<Document> collection, Bson filter) {
      collection.deleteOne(filter);
   }

   public static void deleteMany(MongoCollection<Document> collection, Bson filter) {
      collection.deleteMany(filter);
   }

   public static void main(String[] args) {
      MongoClient client = null;

      try {
         client = connect("db1", "db1", "db1", "192.168.2.127", 27017, true);
         MongoDatabase db = client.getDatabase("db1");
         MongoCollection<Document> collection = db.getCollection("a");
         Bson eq = Filters.eq("_id", "1111");
         Bson regex = Filters.regex("name", "^(?!.*_jm).*$");
         Bson sort = Filters.eq("_id", 1);
         FindIterable<Document> find = collection.find(regex).sort(sort).skip(0).limit(100000);
         MongoCursor<Document> cursor = find.iterator();
         List<Document> results = new ArrayList();
         collection.updateMany((Bson)null, new Document("$unset", new Document("value_copy", 1)), (new UpdateOptions()).upsert(true));

         while(cursor.hasNext()) {
            results.add(cursor.next());
         }
      } catch (Exception e) {
         e.printStackTrace();
      }

   }

   public static int getTableCount(TCoreDatasystem datasystem, String schema) {
      int count = 0;
      List<String> tableList = new ArrayList();

      try {
         MongoClient connect = connect(schema, datasystem.getUsername(), AesTool.decrypt(datasystem.getPassword(), "ghca"), datasystem.getDbip(), Integer.parseInt(datasystem.getDbport()), true);
         if (connect != null) {
            MongoDatabase db = connect.getDatabase(schema);
            if (db != null) {
               MongoCursor var6 = db.listCollectionNames().iterator();

               while(var6.hasNext()) {
                  String str = (String)var6.next();
                  tableList.add(str);
               }
            }
         }

         count = tableList.size();
      } catch (Exception e) {
         e.printStackTrace();
      }

      return count;
   }

   public static int getColumnCount(TCoreDatasystem datasystem, String schema) {
      int count = 0;
      List<String> tableList = new ArrayList();

      try {
         MongoClient connect = connect(schema, datasystem.getUsername(), AesTool.decrypt(datasystem.getPassword(), "ghca"), datasystem.getDbip(), Integer.parseInt(datasystem.getDbport()), true);
         if (connect != null) {
            MongoDatabase db = connect.getDatabase(schema);
            if (db != null) {
               MongoCursor table = db.listCollectionNames().iterator();

               while(table.hasNext()) {
                  String str = (String)table.next();
                  tableList.add(str);
               }
            }
         }

         for(String table : tableList) {
            List<Column> columnList = findAllColumns(connect, schema, table);
            count += columnList.size();
         }
      } catch (Exception e) {
         e.printStackTrace();
      }

      return count;
   }

   public static int getTableColumnCount(TCoreDatasystem datasystem, String schema, String table) {
      int count = 0;

      try {
         MongoClient connect = connect(schema, datasystem.getUsername(), AesTool.decrypt(datasystem.getPassword(), "ghca"), datasystem.getDbip(), Integer.parseInt(datasystem.getDbport()), true);
         List<Column> columnList = findAllColumns(connect, schema, table);
         count = columnList.size();
      } catch (Exception e) {
         e.printStackTrace();
      }

      return count;
   }

   public static List<Column> findAllColumns(MongoClient client, String schema, String collectionName) throws Exception {
      List<Column> columns = new ArrayList();
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      MongoCollection<Document> collection = db.getCollection(collectionName);
      Set<String> columnSet = new HashSet();

      for(Document doc : findAll(collection)) {
         for(Map.Entry<String, Object> entrySet : doc.entrySet()) {
            if (entrySet.getValue() instanceof Document) {
               analysisDocument((String)entrySet.getKey(), (Document)entrySet.getValue(), columnSet);
            } else {
               columnSet.add(entrySet.getKey());
            }
         }
      }

      for(String s : columnSet) {
         Column column = new Column();
         column.setColumnName(s);
         column.setTable(collectionName);
         column.setSchema(schema);
         columns.add(column);
      }

      return columns;
   }

   public static List<String> findAllTables(MongoClient client, String schema) throws Exception {
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      List<String> tables = new ArrayList();
      MongoIterable<String> colls = db.listCollectionNames();
      MongoCursor<String> mongoCursor = colls.iterator();

      while(mongoCursor.hasNext()) {
         String coll = (String)mongoCursor.next();
         if (!coll.contains("system")) {
            tables.add(coll);
         }
      }

      return tables;
   }

   public static void analysisDocument(String prefix, Document document, Set<String> columnSet) {
      for(Map.Entry<String, Object> entrySet : document.entrySet()) {
         if (entrySet.getValue() instanceof Document) {
            analysisDocument(prefix + "." + (String)entrySet.getKey(), (Document)entrySet.getValue(), columnSet);
         } else {
            columnSet.add(prefix + "." + (String)entrySet.getKey());
         }
      }

   }

   public static List<ColumnInfo> getMongodbColumns(TCoreDatasystem datasystem, String schemaName, String tableName) {
      List<ColumnInfo> columnInfoList = new ArrayList();
      List<String> types = new ArrayList();
      Optional<DataBase> dataBase = null;
      Optional<Schema> schema = null;
      Optional<Table> table = null;
      List<DataBase> dataBaseList = DataCache.dataList;
      dataBase = dataBaseList.stream().filter((x) -> x.getIp_port().equals(datasystem.getDbip() + ":" + datasystem.getDbport())).findFirst();
      if (dataBase.isPresent()) {
         List<Schema> schemaList = ((DataBase)dataBase.get()).getSchemaList();
         schema = schemaList.stream().filter((s) -> schemaName.equals(s.getName())).findFirst();
         if (schema.isPresent()) {
            List<Table> tableList = ((Schema)schema.get()).getTableList();
            tableList.stream().forEach((t) -> types.add(t.getName()));
            table = tableList.stream().filter((t) -> tableName.equals(t.getName())).findFirst();
            if (table.isPresent()) {
               for(Column c : ((Table)table.get()).getColumnList()) {
                  ColumnInfo columnInfo = new ColumnInfo();
                  columnInfo.setColumnname(c.getColumnName());
                  columnInfo.setTablename(c.getTable());
                  columnInfo.setTableschem(c.getSchema());
                  columnInfoList.add(columnInfo);
               }
            }
         }
      }

      return columnInfoList;
   }

   public static String getDocumentValue(String columnName, Document document) {
      if (!columnName.contains(".")) {
         Object o = document.get(columnName);
         if (null == o) {
            return "";
         } else {
            return o instanceof String ? (String)o : "";
         }
      } else {
         Object o = document;
         String[] columns = columnName.split("\\.");

         for(int i = 0; i < columns.length; ++i) {
            o = ((Document)o).get(columns[i]);
            if (null == o) {
               return "";
            }

            if (!(o instanceof Document)) {
               if (o instanceof String) {
                  return (String)o;
               }

               return "";
            }
         }

         return "";
      }
   }

   public static List<String> findAllIndexes(MongoClient client, String schema, String collectionName) throws Exception {
      List<String> indexes = new ArrayList();
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      MongoCollection<Document> collection = db.getCollection(collectionName);
      ListIndexesIterable<Document> list = collection.listIndexes();
      MongoCursor<Document> cursor = list.iterator();
      List<Document> result = new ArrayList();

      while(cursor.hasNext()) {
         result.add(cursor.next());
      }

      for(Document document : result) {
         Document document1 = (Document)document.get("key");

         for(Map.Entry<String, Object> entrySet : document1.entrySet()) {
            indexes.add(entrySet.getKey());
         }
      }

      return indexes;
   }

   public static List<String> findAllDataPreview(MongoClient client, String schema, String collectionName) throws Exception {
      List<String> strings = new ArrayList();
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      MongoCollection<Document> collection = db.getCollection(collectionName);

      for(Document doc : findAll(collection)) {
         strings.add(doc.toJson());
      }

      return strings;
   }
}
