package util.getdata;

import bean.Column;
import bean.DataBase;
import bean.Schema;
import bean.Table;
import bean.View;
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.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.bson.BsonDocument;
import org.bson.BsonElement;
import org.bson.BsonJavaScript;
import org.bson.BsonNull;
import org.bson.BsonString;
import org.bson.Document;
import org.bson.conversions.Bson;

public class CacheMongoDB extends CacheData {
   public CacheMongoDB(DataBase dataBase, CountDownLatch cdl) {
      super(dataBase, cdl);
   }

   public List<Schema> getSchema(Statement statement) throws SQLException {
      return null;
   }

   public List<Table> getTable(Statement statement, String schema) throws SQLException {
      return null;
   }

   public List<Column> getColumn(Statement statement, String schema, String table) throws SQLException {
      return null;
   }

   public List<View> getView(Statement statement, String schema) throws SQLException {
      return null;
   }

   public void run() {
      System.out.println("mongodb开始缓存");

      try {
         this.cacheWriteToRedis();
      } catch (Exception e) {
         e.printStackTrace();
      } finally {
         this.getCdl().countDown();
         System.out.println("mongodb結束缓存");
      }

   }

   public List<Schema> cacheToMemory() {
      String username = this.getDataBase().getUsername();
      String databaseName = this.getDataBase().getServername();
      String passwd = this.getDataBase().getPassword();
      String ip_port = this.getDataBase().getIp_port();
      String[] ipports = ip_port.split(":");
      String ip = ipports[0];
      String port = ipports[1];

      try {
         MongoClient client;
         if (username != null && !"".equals(username)) {
            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 dataBase = this.getDataBase();
         return schemas;
      } catch (Exception e) {
         e.printStackTrace();
         return new ArrayList();
      }
   }

   public List<Column> findAllColumns(MongoClient client, String schema, String collectionName) throws Exception {
      List<Column> columns = new ArrayList();
      MongoDatabase db = null;
      db = client.getDatabase(schema);
      List<BsonElement> bsonElements = new ArrayList();
      String erName = "ghca_cache_meta_keys";
      bsonElements.add(new BsonElement("mapreduce", new BsonString(collectionName)));
      bsonElements.add(new BsonElement("map", new BsonJavaScript("function() {\n    for (var key in this) { emit(key, null); }\n  }")));
      bsonElements.add(new BsonElement("reduce", new BsonJavaScript("function(key, stuff) { return null; }")));
      bsonElements.add(new BsonElement("out", new BsonString(erName)));
      Bson b = new BsonDocument(bsonElements);
      db.runCommand(b);
      List<BsonElement> bsonElements1 = new ArrayList();
      bsonElements1.add(new BsonElement("distinct", new BsonString(erName)));
      bsonElements1.add(new BsonElement("key", new BsonString("_id")));
      bsonElements1.add(new BsonElement("query", new BsonNull()));
      Bson b1 = new BsonDocument(bsonElements1);
      Document document1 = db.runCommand(b1);

      for(String s : (List<String>)document1.get("values")) {
         Column column = new Column();
         column.setColumnName(s);
         column.setTable(collectionName);
         column.setSchema(schema);
         columns.add(column);
      }

      db.getCollection(erName).drop();
      return columns;
   }

   public 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 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;
   }
}
