
package com.geniusscansdk.reactnative;

import android.app.Activity;
import android.content.Intent;
import android.util.Log;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.BaseActivityEventListener;
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.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.geniusscansdk.barcodeflow.BarcodeScanFlow;
import com.geniusscansdk.scanflow.PluginBridge;
import com.geniusscansdk.scanflow.PromiseResult;
import com.geniusscansdk.scanflow.ScanFlow;

import java.util.Map;

public class RNGeniusScanModule extends ReactContextBaseJavaModule {
  private final ReactApplicationContext reactContext;
  private Promise mScanPromise;
  private Promise mBarcodeScanPromise;

  public RNGeniusScanModule(ReactApplicationContext reactContext) {
    super(reactContext);
    this.reactContext = reactContext;
    // Add the listener for `onActivityResult`
    reactContext.addActivityEventListener(mActivityEventListener);
  }

  @Override
  public String getName() {
    return "RNGeniusScan";
  }

  // We don't work directly with Promise here as it is a React Native Bridge module
  private void resolvePromiseWithPromiseResult(Promise promise, PromiseResult promiseResult) {
    if (promiseResult.isError) {
      Map<String, String> error = promiseResult.error;
      if (error != null) {
        promise.reject(error.get("code"), error.get("message"), Arguments.makeNativeMap(error));
      } else {
        promise.reject("internal_error", "No error payload");
      }
    } else if (promiseResult.result == null) {
      promise.resolve(null);
    } else {
      promise.resolve(Arguments.makeNativeMap(promiseResult.result));
    }
  }

  private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {

    @Override
    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
      PromiseResult promiseResult = PluginBridge.getPromiseResultFromActivityResult(requestCode, resultCode, intent);
      if (promiseResult != null) {
        Promise promise = null;
        if (requestCode == ScanFlow.REQUEST_CODE) {
          promise = mScanPromise;
          mScanPromise = null;
        } else if (requestCode == BarcodeScanFlow.REQUEST_CODE) {
          promise = mBarcodeScanPromise;
          mBarcodeScanPromise = null;
        }
        if (promise != null) {
          resolvePromiseWithPromiseResult(promise, promiseResult);
        }
      }
    }
  };

  @SuppressWarnings("unused")
  @ReactMethod
  public void scanWithConfiguration(ReadableMap scanOptions, Promise promise) {
    if (mScanPromise != null) {
        Log.w(getName(), "Ignoring scanWithConfiguration call as a scan flow is already in progress");
        return;
    }

    mScanPromise = promise;
    PluginBridge.scanWithConfiguration(getCurrentActivity(), scanOptions.toHashMap());
  }

  @SuppressWarnings("unused")
  @ReactMethod
  public void generateDocument(ReadableMap document, ReadableMap configuration, Promise promise) {
    PromiseResult promiseResult = PluginBridge.generateDocument(getCurrentActivity(), document.toHashMap(), configuration.toHashMap());
    resolvePromiseWithPromiseResult(promise, promiseResult);
  }

  @SuppressWarnings("unused")
  @ReactMethod
  public void setLicenseKey(String licenseKey, boolean autoRefresh, Promise promise) {
    PluginBridge.setLicenseKey(this.reactContext, licenseKey, autoRefresh, "react_native");
    promise.resolve(null);
  }

  @SuppressWarnings("unused")
  @ReactMethod
  public void scanBarcodesWithConfiguration(ReadableMap configuration, Promise promise) {
    if (mBarcodeScanPromise != null) {
        Log.w(getName(), "Ignoring scanBarcodesWithConfiguration call as a barcode scan flow is already in progress");
        return;
    }

    mBarcodeScanPromise = promise;
    PluginBridge.scanBarcodesWithConfiguration(getCurrentActivity(), configuration.toHashMap());
  }
}
