package io.badgeup.sponge.util;

import com.flowpowered.math.vector.Vector3d;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.json.JSONConfigurationLoader;
import org.json.JSONArray;
import org.json.JSONObject;
import org.spongepowered.api.data.DataContainer;
import org.spongepowered.api.data.persistence.DataTranslators;
import org.spongepowered.api.entity.Transform;
import org.spongepowered.api.world.Dimension;
import org.spongepowered.api.world.World;
import org.spongepowered.api.world.extent.Extent;

import java.io.IOException;
import java.io.StringWriter;

public class ObjectSerializers {

    public static JSONObject transformToJSONObject(Transform transform) {
        return new JSONObject()
                .put("Position", vector3dToJSONObject(transform.getPosition()))
                .put("Rotation", vector3dToJSONObject(transform.getRotation()))
                .put("Extent", extentToJSONObject(transform.getExtent()));
    }

    public static JSONObject extentToJSONObject(Extent extent) {
        JSONObject data = new JSONObject()
                .put("id", extent.getUniqueId().toString());

        if (extent instanceof World) {
            World w = (World) extent;

            data.put("Difficulty", w.getDifficulty().getId());
            data.put("Dimension", dimensionToJSONObject(w.getDimension()));
        }

        return data;
    }

    public static JSONObject dimensionToJSONObject(Dimension dimension) {
        return new JSONObject()
                .put("Type", dimension.getType().getId());
    }

    public static JSONObject vector3dToJSONObject(Vector3d vector3d) {
        return new JSONObject()
                .put("x", vector3d.getX())
                .put("y", vector3d.getY())
                .put("z", vector3d.getZ());
    }

    public static JSONObject dataContainerToJSONObject(DataContainer container) {
        ConfigurationNode node = DataTranslators.CONFIGURATION_NODE.translate(container);
        StringWriter writer = new StringWriter();
        try {
            JSONConfigurationLoader.builder().build().saveInternal(node, writer);
            return cleanData(new JSONObject(writer.toString()));
        } catch (IOException e) {
            return new JSONObject();
        }
    }

    private static JSONObject cleanData(JSONObject object) {
        final String dataKey = "Data";
        if (object.has(dataKey)) {
            JSONArray dataArray = object.getJSONArray(dataKey);
            for (int i = 0; i < dataArray.length(); i++) {
                JSONObject data = ((JSONObject) dataArray.get(i)).getJSONObject("ManipulatorData");
                for (String key : data.keySet()) {
                    object.put(key, data.get(key));
                }
            }
            object.remove(dataKey);
        }

        removeFields(object);
        return object;
    }

    private static void removeFields(JSONObject object) {
        object.remove("UnsafeData");
        object.remove("ContentVersion");

        // For entities
        object.remove("EntityClass"); // EntityType will suffice

        // For item stack snapshots
        object.remove("TypeClass"); // ItemType will suffice

        for (String key : object.keySet()) {
            Object value = object.get(key);
            if (value instanceof JSONObject) {
                removeFields((JSONObject) value);
            } else if (value instanceof JSONArray) {
                JSONArray array = (JSONArray) value;
                for (int i = 0; i < array.length(); i++) {
                    Object element = array.get(i);
                    if (element instanceof JSONObject) {
                        removeFields((JSONObject) element);
                    }
                }
            }
        }
    }

}

@@ -2151,25 +2151,26 @@
     
-return cleanData(
+JSONObject data = 
 new 
@@ -2198,17 +2198,70 @@
 tring())
-)
+;%0A            cleanData(data);%0A            return data
 ;%0A      
@@ -2361,26 +2361,20 @@
  static 
-JSONObject
+void
  cleanDa
@@ -2401,47 +2401,8 @@
 ) %7B%0A
-        final String dataKey = %22Data%22;%0A
     
@@ -2420,23 +2420,22 @@
 ect.has(
-dataKey
+%22Data%22
 )) %7B%0A   
@@ -2485,23 +2485,22 @@
 ONArray(
-dataKey
+%22Data%22
 );%0A     
@@ -2818,412 +2818,26 @@
 ove(
-dataKey);%0A        %7D%0A%0A        removeFields(object);%0A        return object;%0A    %7D%0A%0A    private static void removeFields(JSONObject object) %7B%0A        object.remove(%22UnsafeData%22);%0A        object.remove(%22ContentVersion%22);%0A%0A        // For entities%0A        object.remove(%22EntityClass%22); // EntityType will suffice%0A%0A        // For item stack snapshots%0A        object.remove(%22TypeClass%22); // ItemType will suffice
+%22Data%22);%0A        %7D
 %0A%0A  
@@ -2982,36 +2982,33 @@
             
-removeFields
+cleanData
 ((JSONObject
@@ -3318,20 +3318,17 @@
     
-removeFields
+cleanData
 ((JS
@@ -3402,26 +3402,332 @@
      %7D%0A        %7D
+%0A%0A        object.remove(%22UnsafeData%22);%0A        object.remove(%22UnsafeDamage%22);%0A        object.remove(%22ContentVersion%22);%0A%0A        // For entities%0A        object.remove(%22EntityClass%22); // EntityType will suffice%0A%0A        // For item stack snapshots%0A        object.remove(%22TypeClass%22); // ItemType will suffice
 %0A    %7D%0A%0A%7D%0A

Fix DataContainer JSON cleanup