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.string.AesTool;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.MongoIterable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.bson.Document;

public class CacheMongodb implements Runnable {
   private DataSystemServiceImpl dataSystemService;
   private TCoreDatasystem datasystem;
   private CountDownLatch cdl;

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

   public void run() {
      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);
      }

      String ip = this.datasystem.getDbip();
      String port = this.datasystem.getDbport();
      String username = this.datasystem.getUsername();
      String passwd = this.datasystem.getPassword();
      String databaseName = this.datasystem.getDbservername();

      try {
         MongoClient client;
         if (username != null && !"".equals(username)) {
            passwd = !"1".equals(this.datasystem.getFlag()) && !"4".equals(this.datasystem.getFlag()) ? this.datasystem.getPassword() : AesTool.decrypt(this.datasystem.getPassword(), "ghca");
            client = this.connect(databaseName, username, passwd, ip, Integer.valueOf(port), true);
         } else {
            client = this.connect(databaseName, username, passwd, ip, Integer.valueOf(port), false);
         }

         List<String> dblist = client.getDatabaseNames();
         List<Schema> schemas = new ArrayList();

         for(String dbname : dblist) {
            MongoDatabase db = client.getDatabase(dbname);
            Schema schema = new Schema(dbname);
            List<Table> 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")) {
                  List<Column> columns = this.findAllColumns(client, dbname, coll);
                  Table table = new Table(coll, dbname);
                  table.setColumnList(columns);
                  tables.add(table);
               }
            }

            schema.setTableList(tables);
            schemas.add(schema);
         }

         dataBase.setSchemaList(schemas);
         dataBase.easyCache = new DBEasyCache(dataBase);
         dataBase.easyCache.init();
      } catch (Exception e) {
         e.printStackTrace();
      }

   }

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

   }

   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 void main(String[] args) {
      TCoreDatasystem datasystem = new TCoreDatasystem();
      datasystem.setDbip("192.168.2.127");
      datasystem.setDbport("27017");
      datasystem.setServername("db1");
      datasystem.setUsername("db1");
      datasystem.setPassword("db1");
      CountDownLatch cdl = new CountDownLatch(1);
      (new CacheMongodb((DataSystemServiceImpl)null, datasystem, cdl)).run();
   }
}
