// NOTE — LOCAL DEVELOPMENT VS PRODUCTION
//
// When developing this library locally, the example app and the library
// use separate node_modules, creating two distinct instances of
// `react-native`. In this scenario, NativeEventEmitter events emitted by
// the library will not reach the example app.
//
// For LOCAL TESTING, uncomment the line below to ensure both the library
// and the demo app use the same React Native instance:
// import { NativeEventEmitter, NativeModules, Platform } from '../example/node_modules/react-native';
//
// ⚠️ Do NOT commit or publish the library using that import.
//
// For PRODUCTION, always use the standard import:
import { NativeEventEmitter, NativeModules, Platform } from 'react-native';

import type { FaceConfig } from './config/FaceConfig';
import type { FaceAttributes } from './FaceAttributes';
import { mergeConfigs } from './utils/Utils';

const LINKING_ERROR =
  `The package '@biopassid/face-sdk-react-native' doesn't seem to be linked. Make sure: \n\n` +
  Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
  '- You rebuilt the app after installing the package\n' +
  '- You are not using Expo Go\n';

const FaceSdkReactNative = NativeModules.FaceSdkReactNative
  ? NativeModules.FaceSdkReactNative
  : new Proxy(
      {},
      {
        get() {
          throw new Error(LINKING_ERROR);
        },
      }
    );

const eventEmitter = new NativeEventEmitter(FaceSdkReactNative);

const supportedEvents = [
  'face-sdk-react-native/onFaceCapture',
  'face-sdk-react-native/onFaceDetected',
];

export interface TakeFaceOptions {
  config: FaceConfig;
  onFaceCapture: (image: string, faceAttributes: FaceAttributes | null) => void;
  onFaceDetected?: (faceAttributes: FaceAttributes) => void;
}

interface OnFaceCaptureEvent {
  image: string;
  faceAttributes: FaceAttributes | null;
}

interface OnFaceDetectedEvent {
  faceAttributes: FaceAttributes;
}

export async function takeFace(
  options: TakeFaceOptions
): Promise<void | never> {
  try {
    const newConfig = mergeConfigs(options.config);

    supportedEvents.map((eventName: string) => {
      eventEmitter.removeAllListeners(eventName);

      if (eventName === 'face-sdk-react-native/onFaceCapture') {
        eventEmitter.addListener(eventName, (event: OnFaceCaptureEvent) => {
          options.onFaceCapture(event.image, event.faceAttributes);
        });
      } else if (eventName === 'face-sdk-react-native/onFaceDetected') {
        eventEmitter.addListener(eventName, (event: OnFaceDetectedEvent) => {
          if (options.onFaceDetected != null) {
            options.onFaceDetected(event.faceAttributes);
          }
        });
      }
    });

    await FaceSdkReactNative.takeFace(newConfig);
  } catch (error) {
    console.error(`Unknown error: ${error}`);
  }
}
