package com.snapmint.rn;

import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import java.util.Iterator;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Utils {
  public static JSONObject readableMapToJson(ReadableMap readableMap) throws JSONException {
    JSONObject jsonObject = new JSONObject();
    ReadableMapKeySetIterator iterator = readableMap.keySetIterator();
    while (iterator.hasNextKey()) {
      String key = iterator.nextKey();
      ReadableType type = readableMap.getType(key);
      switch (type) {
        case Null:
          jsonObject.put(key, JSONObject.NULL);
          break;
        case Boolean:
          jsonObject.put(key, readableMap.getBoolean(key));
          break;
        case Number:
          jsonObject.put(key, readableMap.getDouble(key));
          break;
        case String:
          jsonObject.put(key, readableMap.getString(key));
          break;
        case Map:
          jsonObject.put(key, readableMapToJson(readableMap.getMap(key)));
          break;
        case Array:
          jsonObject.put(key, readableArrayToJson(readableMap.getArray(key)));
          break;
      }
    }
    return jsonObject;
  }

  public static JSONArray readableArrayToJson(
    com.facebook.react.bridge.ReadableArray readableArray
  ) throws JSONException {
    JSONArray jsonArray = new JSONArray();
    for (int i = 0; i < readableArray.size(); i++) {
      ReadableType type = readableArray.getType(i);
      switch (type) {
        case Null:
          jsonArray.put(JSONObject.NULL);
          break;
        case Boolean:
          jsonArray.put(readableArray.getBoolean(i));
          break;
        case Number:
          jsonArray.put(readableArray.getDouble(i));
          break;
        case String:
          jsonArray.put(readableArray.getString(i));
          break;
        case Map:
          jsonArray.put(readableMapToJson(readableArray.getMap(i)));
          break;
        case Array:
          jsonArray.put(readableArrayToJson(readableArray.getArray(i)));
          break;
      }
    }
    return jsonArray;
  }

  public static WritableMap jsonToWritableMap(JSONObject jsonObject) {
    WritableMap writableMap = new WritableNativeMap();
    Iterator<String> iterator = jsonObject.keys();
    while (iterator.hasNext()) {
      String key = iterator.next();
      try {
        Object value = jsonObject.get(key);
        if (value instanceof JSONObject) {
          writableMap.putMap(key, jsonToWritableMap((JSONObject) value));
        } else if (value instanceof JSONArray) {
          writableMap.putArray(key, jsonToWritableArray((JSONArray) value));
        } else if (value instanceof String) {
          writableMap.putString(key, (String) value);
        } else if (value instanceof Number) {
          writableMap.putDouble(key, ((Number) value).doubleValue());
        } else if (value instanceof Boolean) {
          writableMap.putBoolean(key, ((Boolean) value).booleanValue());
        } else {
          writableMap.putNull(key);
        }
      } catch (JSONException e) {
        // Do nothing
      }
    }
    return writableMap;
  }

  public static WritableArray jsonToWritableArray(JSONArray jsonArray) {
    WritableArray writableArray = new WritableNativeArray();
    for (int i = 0; i < jsonArray.length(); i++) {
      try {
        Object value = jsonArray.get(i);
        if (value instanceof JSONObject) {
          writableArray.pushMap(jsonToWritableMap((JSONObject) value));
        } else if (value instanceof JSONArray) {
          writableArray.pushArray(jsonToWritableArray((JSONArray) value));
        } else if (value instanceof String) {
          writableArray.pushString((String) value);
        } else if (value instanceof Number) {
          writableArray.pushDouble(((Number) value).doubleValue());
        } else if (value instanceof Boolean) {
          writableArray.pushBoolean((Boolean) value);
        } else {
          writableArray.pushNull();
        }
      } catch (JSONException e) {
        // Do nothing
      }
    }
    return writableArray;
  }
}
