package com.castlabs.reactnative.utils;

import androidx.annotation.NonNull;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableType;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;

public class JsonMap {
  private final ReadableMap map;

  public JsonMap(@NonNull ReadableMap map) {
    this.map = map;
  }

  public Optional<Integer> getInteger(@NonNull String key) {
    Optional<Integer> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Number && !map.isNull(key)) {
      result = Optional.of(map.getInt(key));
    }

    return result;
  }

  public Optional<Long> getLong(@NonNull String key) {
    Optional<Long> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Number && !map.isNull(key)) {
      result = Optional.of((long) map.getDouble(key));
    }

    return result;
  }

  public Optional<Float> getFloat(@NonNull String key) {
    Optional<Float> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Number && !map.isNull(key)) {
      result = Optional.of((float) map.getDouble(key));
    }

    return result;
  }

  public Optional<String> getString(@NonNull String key) {
    Optional<String> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.String && !map.isNull(key)) {
      String value = map.getString(key);
      if (value != null && !value.isEmpty()) {
        result = Optional.of(value);
      }
    }

    return result;
  }

  public Optional<Boolean> getBoolean(@NonNull String key) {
    Optional<Boolean> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Boolean && !map.isNull(key)) {
      result = Optional.of(map.getBoolean(key));
    }

    return result;
  }

  public Optional<JsonMap> getMap(@NonNull String key) {
    Optional<JsonMap> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Map && !map.isNull(key)) {
      result = Optional.of(new JsonMap(map.getMap(key)));
    }

    return result;
  }

  public Optional<JsonArray> getArray(@NonNull String key) {
    Optional<JsonArray> result = Optional.empty();

    if (map.hasKey(key) && map.getType(key) == ReadableType.Array && !map.isNull(key)) {
      result = Optional.of(new JsonArray(map.getArray(key)));
    }

    return result;
  }

  public Map<String, Object> toMap() {
    Map<String, Object> result = new HashMap<>();

    Iterator<Map.Entry<String, Object>> it = iterator();
    while (it.hasNext()) {
      Map.Entry<String, Object> entry = it.next();
      result.put(entry.getKey(), entry.getValue());
    }

    return result;
  }

  public Iterator<Map.Entry<String, Object>> iterator() {
    return map.getEntryIterator();
  }
}
