content: package com.ammarahmed.mmkv;
  
  import android.os.Bundle;
  import android.os.Parcel;
  import android.os.Parcelable;
  import android.util.Log;
  
  import androidx.annotation.Nullable;
  
  import com.facebook.react.bridge.Arguments;
  import com.facebook.react.bridge.Callback;
  import com.facebook.react.bridge.JavaScriptContextHolder;
  import com.facebook.react.bridge.ReactApplicationContext;
  import com.facebook.react.bridge.ReactContextBaseJavaModule;
  import com.facebook.react.bridge.ReactMethod;
  import com.facebook.react.bridge.ReadableMap;
  import com.facebook.react.bridge.WritableArray;
  import com.facebook.react.bridge.WritableMap;
  import com.facebook.react.module.annotations.ReactModule;
  import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
  import com.google.gson.Gson;
  import com.ammarahmed.mmkv.MMKV;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Set;
  
  @ReactModule(name = RNMMKVModule.NAME)
  public class RNMMKVModule extends MmkvStorageSpec {
  
      public static final String NAME = "MMKVStorage";
  
      private final ReactApplicationContext reactContext;
      private SecureKeystore secureKeystore;
  
      static {
          System.loadLibrary("rnmmkv");
      }
  
      private native void nativeInstall(long jsi, String rootPath);
  
      private native void destroy();
  
      public RNMMKVModule(ReactApplicationContext reactContext) {
          super(reactContext);
          this.reactContext = reactContext;
          secureKeystore = new SecureKeystore(reactContext);
      }
  
      public void installLib(JavaScriptContextHolder reactContext, String rootPath) {}
  
      // Installing JSI Bindings as done by
      // https://github.com/mrousavy/react-native-mmkv
      @ReactMethod(isBlockingSynchronousMethod = true)
      public boolean install() {
  
          String rootPath = reactContext.getFilesDir().getAbsolutePath() + "/mmkv";
          JavaScriptContextHolder jsContext = getReactApplicationContext().getJavaScriptContextHolder();
          if (jsContext.get() != 0) {
              migrate();
              this.nativeInstall(
                      jsContext.get(),
                      rootPath
              );
              return true;
          } else {
              Log.e("RNMMKVModule","JSI Runtime is not available in debug mode");
              return false;
          }
  
      }
  
      @Override
      public void initialize() {
          super.initialize();
      }
  
      public void migrate() {
          MMKV.initialize(reactContext);
          MMKV kv = MMKV.mmkvWithID("mmkvIDStore");
          boolean hasKey = kv.containsKey("mmkvIdStore");
          HashMap<String, Object> IdStore = new HashMap<>();
          if (hasKey) {
              Bundle mmkvIdStore = kv.decodeParcelable("mmkvIdStore", Bundle.class);
              IdStore = (HashMap<String, Object>) mmkvIdStore.getSerializable("mmkvIdStore");
              Set<String> keys = IdStore.keySet();
              for (String key : keys) {
                  HashMap<String, Object> child = (HashMap<String, Object>) IdStore.get(key);
  
                  boolean isEncrypted = false;
                  if (child.containsKey("encrypted")) {
                    isEncrypted  = (boolean) child.get("encrypted");
                  }
                  if (isEncrypted && !child.containsKey("alias")) {
                      Set<String> storeKeys =  child.keySet();
                      String alias = (String) child.get("alias");
                      for (String storeKey: storeKeys) {
                          if (storeKey == null) continue;
                          if (!storeKey.equals("ID") && !storeKey.equals("encrypted")) {
                              alias = (String) child.get(storeKey);
                          }
                      }
                      child.put("alias",alias);
                  }
                  Gson gson = new Gson();
                  String json = gson.toJson(child);
                  kv.encode(key, json);
                  
                  if (isEncrypted) {
                      String alias = (String) child.get("alias");
                      if (secureKeystore.secureKeyExists(alias)) {
                          String cKey = secureKeystore.getSecureKey(alias);
                          MMKV kvv = MMKV.mmkvWithID(key, MMKV.SINGLE_PROCESS_MODE, cKey);
                           writeToJSON(kvv);
                      }
                  } else {
                      MMKV kvv = MMKV.mmkvWithID(key, MMKV.SINGLE_PROCESS_MODE);
                      writeToJSON(kvv);
                  }
  
              }
              kv.removeValueForKey("mmkvIdStore");
          }
      }
  
      public void writeToJSON(MMKV kvv) {
          Gson gson = new Gson();
          Set<String> mapIndex = new HashSet<>();
          mapIndex = kvv.decodeStringSet("mapIndex", mapIndex);
          if (mapIndex != null) {
              for (String string : mapIndex) {
                  Bundle bundle = kvv.decodeParcelable(string, Bundle.class);
                  if (bundle != null) {
                      WritableMap map = Arguments.fromBundle(bundle);
                      String obj = gson.toJson(map.toHashMap());
                      kvv.encode(string, obj);
                  }
  
              }
          }
          Set<String> arrayIndex = new HashSet<>();
          arrayIndex = kvv.decodeStringSet("arrayIndex", arrayIndex);
          if (arrayIndex != null) {
              for (String string : arrayIndex) {
                  Bundle bundle = kvv.decodeParcelable(string, Bundle.class);
                  if (bundle != null) {
                      WritableMap map = Arguments.fromBundle(bundle);
                      if (map.getArray(string) != null) {
                          ArrayList<Object> list = map.getArray(string).toArrayList();
                          String obj = gson.toJson(list);
                          kvv.encode(string, obj);
                      }
  
                  }
  
              }
          }
  
  
          Set<String> intIndex = new HashSet<>();
          if (intIndex != null) {
              intIndex = kvv.decodeStringSet("intIndex", intIndex);
              for (String key : intIndex) {
                  int val = kvv.decodeInt(key);
                  double d = val;
                  kvv.encode(key, d);
              }
              kvv.encode("numberIndex", intIndex);
          }
  
  
      }
  
      @Override
      public String getName() {
          return "MMKVNative";
      }
  
      public boolean secureKeyExists(String key) {
          return secureKeystore.secureKeyExists(key);
      }
  
      public void removeSecureKey(String key) {
          secureKeystore.removeSecureKey(key);
      }
  
      public void setSecureKey(String key, String value) {
          secureKeystore.setSecureKey(key, value);
      }
  
      public String getSecureKey(String key) {
          return secureKeystore.getSecureKey(key);
      }
  
  }