package com.kodcu.converter;

import com.mongodb.MongoNamespace;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import org.bson.Document;

import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by Hakan on 5/18/2015.
 */
public class JSONConverter {

    private final Logger logger = Logger.getLogger("JSONConverter");
    private final MongoCollection<Document> collection;

    public JSONConverter(final MongoCollection<Document> collection) {
        this.collection = collection;
    }

    public StringBuilder buildBulkJsonFile() {
        FindIterable<Document> results = collection.find();
        MongoCursor<Document> cursor = results.iterator();
        StringBuilder sb = new StringBuilder();

        while (cursor.hasNext()) {
            Document doc = cursor.next();
            Set<Map.Entry<String, Object>> set = doc.entrySet();

            JsonObjectBuilder jsonObj = Json.createObjectBuilder();

            set.stream().forEach(entry -> {
                if (entry.getKey().equals("_id")) {
                    MongoNamespace namespace = collection.getNamespace();
                    JsonObjectBuilder create = Json.createObjectBuilder();
                    create.add("create", Json.createObjectBuilder()
                            .add("_index", namespace.getDatabaseName())
                            .add("_type", namespace.getCollectionName())
                            .add("_id", entry.getValue().toString()));
                    sb.append(create.build().toString());
                    sb.append(System.lineSeparator());
                } else {
                    this.buildJson(jsonObj, entry, sb);
                }
            });

            sb.append(jsonObj.build().toString());
            sb.append(System.lineSeparator());
        }

        return sb;
    }

    private void buildJson(JsonObjectBuilder jsonObj, Map.Entry<String, Object> entry, StringBuilder sb) {
        Object value = entry.getValue();
        String field = entry.getKey();
        if (Objects.isNull(value)) {
            jsonObj.add(field, JsonValue.NULL);
        } else {
            if (value instanceof Document) {
                Document doc = (Document) value;
                Set<Map.Entry<String, Object>> set = doc.entrySet();
                JsonObjectBuilder sub = Json.createObjectBuilder();

                set.stream().forEach(subEntry -> {
                    this.buildJson(sub, subEntry, sb);
                });
                jsonObj.add(field, sub);
            } else if (value instanceof Boolean) {
                Boolean bool = (Boolean) value;
                jsonObj.add(field, bool.booleanValue());
            } else if (value instanceof Number) {
                Number number = (Number) value;
                jsonObj.add(field, number.doubleValue());
            } else if (value instanceof Date) {
                Date date = (Date) value;
                jsonObj.add(field, date.toString());
            } else if (value instanceof ArrayList) {
                ArrayList list = (ArrayList) value;
                JsonArrayBuilder sub = Json.createArrayBuilder();
                list.forEach(item -> {
                    this.buildJson(sub, item, sb);
                });
                jsonObj.add(field, sub);
            } else {
                jsonObj.add(field, value.toString());
            }
        }
    }


    private void buildJson(JsonArrayBuilder jsonArray, Object value, StringBuilder sb) {
        if (Objects.isNull(value)) {
            jsonArray.add(JsonValue.NULL);
        } else {
            if (value instanceof Document) {
                Document doc = (Document) value;
                Set<Map.Entry<String, Object>> set = doc.entrySet();
                JsonObjectBuilder subObj = Json.createObjectBuilder();
                set.stream().forEach(entry -> {
                    this.buildJson(subObj, entry, sb);
                });
                jsonArray.add(subObj);
            } else if (value instanceof Boolean) {
                Boolean bool = (Boolean) value;
                jsonArray.add(bool.booleanValue());
            } else if (value instanceof Number) {
                Number number = (Number) value;
                jsonArray.add(number.doubleValue());
            } else if (value instanceof Date) {
                Date date = (Date) value;
                jsonArray.add(date.toString());
            } else if (value instanceof ArrayList) {
                ArrayList list = (ArrayList) value;
                JsonArrayBuilder sub = Json.createArrayBuilder();
                list.forEach(item -> {
                    this.buildJson(sub, item, sb);
                });
                jsonArray.add(sub);
            } else {
                jsonArray.add(value.toString());
            }
        }
    }

    public void writeToFile(StringBuilder sb, String outFile) {
        try {
            File file = new File(outFile.concat(".json"));
            Files.write(file.toPath(), sb.toString().getBytes(Charset.forName("UTF-8")));
        } catch (Exception e) {
            logger.severe(e.getMessage());
        }
    }
}




@@ -180,16 +180,48 @@
 Cursor;%0A
+import org.apache.log4j.Logger;%0A
 import o
@@ -238,16 +238,16 @@
 cument;%0A
-
 %0Aimport 
@@ -380,17 +380,20 @@
 java.io.
-*
+File
 ;%0Aimport
@@ -470,73 +470,8 @@
 l.*;
-%0Aimport java.util.logging.Level;%0Aimport java.util.logging.Logger;
 %0A%0A/*
@@ -591,17 +591,16 @@
 tLogger(
-%22
 JSONConv
@@ -604,17 +604,22 @@
 onverter
-%22
+.class
 );%0A    p
@@ -778,32 +778,32 @@
 lection;%0A    %7D%0A%0A
-
     public Strin
@@ -829,24 +829,82 @@
 sonFile() %7B%0A
+        // TODO: Her 1000 veride dosyaya yaz yap%C4%B1labilir?%0A
         Find
@@ -5458,14 +5458,13 @@
 ger.
-severe
+error
 (e.g
@@ -5474,16 +5474,87 @@
 essage()
+, e.fillInStackTrace());%0A        %7D finally %7B%0A            sb.setLength(0
 );%0A     

Update converter