package com.seonreactnativemobilewrapper;
import java.util.UUID;

import com.facebook.react.bridge.Promise;
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.module.annotations.ReactModule;

import androidx.annotation.NonNull;
import io.seon.androidsdk.dto.SeonGeolocationConfig;
import io.seon.androidsdk.dto.SeonGeolocationConfigBuilder;
import io.seon.androidsdk.exception.BehaviouralMonitoringException;
import io.seon.androidsdk.exception.SeonException;
import io.seon.androidsdk.service.Seon;
import io.seon.androidsdk.service.SeonBuilder;
import io.seon.androidsdk.service.SeonCallbackWithGeo;
import org.json.JSONException;
import org.json.JSONObject;

@ReactModule(name = SeonReactNativeMobileWrapperModule.NAME)
public class SeonReactNativeMobileWrapperModule extends ReactContextBaseJavaModule {
  public static final String NAME = "SeonReactNativeMobileWrapperSpec";
  private Seon m_seon;
  private SeonGeolocationConfig mGeoConfig;

  public SeonReactNativeMobileWrapperModule(ReactApplicationContext reactContext) {
    super(reactContext);
    String sessionID = UUID.randomUUID().toString();
    m_seon = new SeonBuilder()
      .withContext(reactContext.getApplicationContext())
      .withSessionId(sessionID)
      .build();
    // Initialize default geolocation config
    mGeoConfig = new SeonGeolocationConfigBuilder().build();
  }
  public SeonReactNativeMobileWrapperModule(ReactApplicationContext reactContext,String sessionID) {
    super(reactContext);
    m_seon = new SeonBuilder()
    .withContext(reactContext.getApplicationContext())
    .withSessionId(sessionID)
    .build();
  }

  @Override
  @NonNull
  public String getName() {
    return NAME;
  }

  @ReactMethod
    public void setSessionId(String sessionId, Promise promise) {
      try{
        m_seon.setSessionId(sessionId);
        promise.resolve(null);
      }catch(Exception e){
        promise.reject("setSessionId",e);
      }
    }

    @ReactMethod
    public void setLoggingEnabled(boolean enabled, Promise promise) {
      try{
        m_seon.setLoggingEnabled(enabled);
        promise.resolve(null);
      }catch(Exception e){
        promise.reject("setLoggingEnabled", e);
      }
    }

    @ReactMethod
    public void getFingerprintBase64(Promise seonCallback) {
      if (mGeoConfig.isGeolocationEnabled()){
          try {
            m_seon.getFingerprintBase64(new SeonCallbackWithGeo() {
              @Override
              public void onComplete(String response) {
                  seonCallback.resolve(response);
              }

              @Override
              public void onCompleteWithGeoFailure(String response, int geoStatusCode) {
                seonCallback.reject("SEON_GEO_FAILURE_CODE:"+String.valueOf(geoStatusCode), "SEON_GEO_FAILURE_CODE: "+String.valueOf(geoStatusCode) + " RESPONSE:"+ response);
              }
          });
          } catch (Exception e) {
            seonCallback.reject("SEON_ERROR",e);
          }
      }
      else{
        try {
          m_seon.getFingerprintBase64(seonCallback::resolve);
        } catch (Exception e) {
          seonCallback.reject("SEON_ERROR",e);
        }
      }
    }

    @ReactMethod
    public void startBehaviourMonitoring(Promise promise) {
        try {
            m_seon.startBehaviourMonitoring();
            promise.resolve(null);
        } catch (Exception e) {
            promise.reject("BEHAVIOUR_ERROR", e);
        }
    }

    @ReactMethod
    public void stopBehaviourMonitoring(Promise promise) {
        try {
            m_seon.stopBehaviourMonitoring(fp -> {
                promise.resolve(fp);
            });
        } catch (BehaviouralMonitoringException e) {
            promise.reject("BEHAVIOUR_ERROR", e);
        } catch (SeonException e) {
            promise.reject("BEHAVIOUR_ERROR", e);
        }
    }

  @ReactMethod
  public void setGeolocationEnabled(boolean enabled, Promise promise) {
      m_seon.setGeolocationEnabled(enabled);
      promise.resolve(true);
  }

  @ReactMethod
  public void setGeoLocationConfig(ReadableMap config, Promise promise) {
    SeonGeolocationConfigBuilder configBuilder = new SeonGeolocationConfigBuilder();

    if (config.hasKey("geolocationEnabled")){
        configBuilder.withGeolocationEnabled(config.getBoolean("geolocationEnabled"));
    }
    if (config.hasKey("prefetchEnabled")) {
        configBuilder.withPrefetchEnabled(config.getBoolean("prefetchEnabled"));
    }
    if (config.hasKey("geolocationServiceTimeoutMs")) {
        configBuilder.withGeolocationServiceTimeoutMs(config.getInt("geolocationServiceTimeoutMs"));
    }
    if (config.hasKey("maxGeoLocationCacheAgeSec")) {
        configBuilder.withMaxGeoLocationCacheAgeSec(config.getInt("maxGeoLocationCacheAgeSec"));
    }

    SeonGeolocationConfig seonGeolocationConfig = configBuilder.build();
    m_seon.setGeoLocationConfig(seonGeolocationConfig);
    mGeoConfig = seonGeolocationConfig;
    promise.resolve(true);
  }

}

