package util.sqlparse.visitor.mongo.test;

import com.alibaba.fastjson.JSONObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.List;
import java.util.UUID;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.bson.BSON;
import org.bson.BSONObject;
import org.bson.BasicBSONDecoder;
import org.bson.BsonBinaryReader;
import org.bson.BsonBinarySubType;
import org.bson.BsonBinaryWriter;
import org.bson.BsonDocument;
import org.bson.BsonInt64;
import org.bson.BsonJavaScript;
import org.bson.ByteBuf;
import org.bson.Document;
import org.bson.codecs.BsonDocumentCodec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.EncoderContext;
import org.bson.conversions.Bson;
import org.bson.io.BasicOutputBuffer;
import org.bson.json.JsonMode;
import org.bson.json.JsonReader;
import org.bson.json.JsonWriterSettings;
import org.bson.types.Binary;
import org.bson.types.ObjectId;

public class BsonTest {
   public static void main(String[] args) throws DecoderException {
      bsonDecode();
   }

   public static void main2() {
      MongoClient client = new MongoClient("127.0.0.1", 27017);
      MongoDatabase database = client.getDatabase("test");
      MongoCollection<Document> collection = database.getCollection("te");
      System.out.println(collection.find().first());

      try {
         Bson command = new BsonDocument("dbStats", new BsonInt64(1L));
         Document commandResult = database.runCommand(command);
         System.out.println("dbStats: " + commandResult.toJson());
         String hex = "007b0000000266696e64000a000000696e76656e746f7279000366696c74657200280000000474616773001d000000023000040000007265640002310006000000626c616e6b000000036c736964001e000000056964001000000004d12a705c73d44ea8980ddec55dd75d7300022464620005000000746573740000";
         byte[] bytes = Hex.decodeHex(hex.toCharArray());
         BsonDocument test = (new BsonDocumentCodec()).decode(new BsonBinaryReader(ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN)), DecoderContext.builder().build());
         test.remove("$db");
         commandResult = database.runCommand(test);
         System.out.println("result: " + commandResult.toJson());
         BasicOutputBuffer output = new BasicOutputBuffer();
         (new BsonDocumentCodec()).encode(new BsonBinaryWriter(output), test, EncoderContext.builder().build());
         List<ByteBuf> ob = output.getByteBuffers();
         byte[] bytes3 = output.toByteArray();
         System.out.println(Hex.encodeHex(bytes3));
         BsonDocument test3 = (new BsonDocumentCodec()).decode(new BsonBinaryReader(ByteBuffer.wrap(bytes3).order(ByteOrder.LITTLE_ENDIAN)), DecoderContext.builder().build());
         System.out.println(test3);
      } catch (MongoException me) {
         System.err.println("An error occurred: " + me);
      } catch (DecoderException me) {
         System.err.println("An error occurred: " + me);
      }

   }

   private static void bsonDecode() throws DecoderException {
      String hex = "e70000000261676772656761746500070000006f72646572730004706970656c696e6500830000000330007b00000003246d61746368006e00000003246578707200620000000424616e6400570000000330002400000004246774001a0000000230000700000024707269636500103100640000000000033100280000000424677465001d0000000230000a000000247175616e7469747900103100050000000000000000000003637572736f72000500000000036c736964001e000000056964001000000004425309d427094734b76eb480aa4c253f00022464620005000000746573740000";
      byte[] bytes = Hex.decodeHex(hex.toCharArray());
      BSONObject decode = BSON.decode(bytes);
      System.out.println(decode.toString());
      Bson bson = Filters.gt("a", 10);
      BsonDocument bsonDocument = bson.toBsonDocument(BsonDocument.class, MongoClient.getDefaultCodecRegistry());
      System.out.println(bsonDocument.toString());
      byte[] array = (new BigInteger("130000001069734d6173746572000100000000", 16)).toByteArray();
      BasicBSONDecoder decoder = new BasicBSONDecoder();
      BSONObject bsonObject = decoder.readObject(array);
      System.out.println(bsonObject.toString());
      JSONObject json = new JSONObject(decode.toMap());
      System.out.println(json);
      BsonDocument test = (new BsonDocumentCodec()).decode(new BsonBinaryReader(ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN)), DecoderContext.builder().build());
      System.out.println(test.toString());
      BsonDocument test2 = (new BsonDocumentCodec()).decode(new JsonReader(test.toString()), DecoderContext.builder().build());
      System.out.println(test2.toString());
      Document myDoc = new Document();

      try {
         myDoc.append("_id", new ObjectId("507f1f77bcf86cd799439012")).append("myNumber", 11223344).append("id", new Binary(BsonBinarySubType.UUID_STANDARD, "ox8E0sqfQzW4ULnhWahC8A==".getBytes("UTF-8")));
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      }

      JsonWriterSettings settings = JsonWriterSettings.builder().outputMode(JsonMode.EXTENDED).build();
      System.out.println(myDoc.toJson(settings));
      UUID uuid4 = UUID.randomUUID();
      System.out.println(uuid4);
      byte[] bytes2 = new byte[16];
      writeLongToArrayLittleEndian(bytes2, 0, uuid4.getMostSignificantBits());
      writeLongToArrayLittleEndian(bytes2, 8, uuid4.getLeastSignificantBits());
      Document myDoc2 = new Document();
      myDoc2.append("_id", new ObjectId("507f1f77bcf86cd799439012")).append("myNumber", 11223344).append("id", new Binary(BsonBinarySubType.UUID_STANDARD, bytes2));
      System.out.println(myDoc2.toJson(settings));
      Document myDoc3 = new Document();
      myDoc3.append("id", new Binary(BsonBinarySubType.UUID_STANDARD, bytes2));
      System.out.println(myDoc3.toJson(settings));
      BsonDocument myDoc4 = new BsonDocument();
      myDoc4.append("id", new BsonJavaScript("function() {emit(this.cust_id, this.price);"));
      System.out.println(myDoc4.toJson(settings));
   }

   private static void writeLongToArrayLittleEndian(byte[] bytes, int offset, long x) {
      bytes[offset + 7] = (byte)((int)(255L & x));
      bytes[offset + 6] = (byte)((int)(255L & x >> 8));
      bytes[offset + 5] = (byte)((int)(255L & x >> 16));
      bytes[offset + 4] = (byte)((int)(255L & x >> 24));
      bytes[offset + 3] = (byte)((int)(255L & x >> 32));
      bytes[offset + 2] = (byte)((int)(255L & x >> 40));
      bytes[offset + 1] = (byte)((int)(255L & x >> 48));
      bytes[offset + 0] = (byte)((int)(255L & x >> 56));
   }
}
