export type AuthenticateIOS = {
  description?: string;
  fallbackEnabled?: boolean;
};
export type AuthenticateAndroid = {
  title?: string;
  subTitle?: string;
  description?: string;
  cancelButton?: string;
  onAttempt?: (error: FingerprintScannerError) => void;
};

export type Biometrics = "Touch ID" | "Face ID" | "Biometrics";

export type Errors =
  | { name: "AuthenticationNotMatch"; message: "No match" }
  | {
      name: "AuthenticationFailed";
      message: "Authentication was not successful because the user failed to provide valid credentials";
    }
  | {
      name: "AuthenticationTimeout";
      message: "Authentication was not successful because the operation timed out.";
    }
  | {
      name: "AuthenticationProcessFailed";
      message: "Sensor was unable to process the image. Please try again.";
    }
  | {
      name: "UserCancel";
      message: "Authentication was canceled by the user - e.g. the user tapped Cancel in the dialog";
    }
  | {
      name: "UserFallback";
      message: "Authentication was canceled because the user tapped the fallback button (Enter Password)";
    }
  | {
      name: "SystemCancel";
      message: "Authentication was canceled by system - e.g. if another application came to foreground while the authentication dialog was up";
    }
  | {
      name: "PasscodeNotSet";
      message: "Authentication could not start because the passcode is not set on the device";
    }
  | {
      name: "FingerprintScannerNotAvailable";
      message: "	Authentication could not start because Fingerprint Scanner is not available on the device";
    }
  | {
      name: "FingerprintScannerNotEnrolled";
      message: "	Authentication could not start because Fingerprint Scanner has no enrolled fingers";
    }
  | {
      name: "FingerprintScannerUnknownError";
      message: "Could not authenticate for an unknown reason";
    }
  | {
      name: "FingerprintScannerNotSupported";
      message: "Device does not support Fingerprint Scanner";
    }
  | {
      name: "DeviceLocked";
      message: "Authentication was not successful, the device currently in a lockout of 30 seconds";
    }
  | {
      name: "DeviceLockedPermanent";
      message: "Authentication was not successful, device must be unlocked via password.";
    }
  | {
      name: "DeviceOutOfMemory";
      message: "Authentication could not proceed because there is not enough free memory on the device.";
    }
  | {
      name: "HardwareError";
      message: "A hardware error occurred.";
    };

export type FingerprintScannerError = { biometric: Biometrics } & Errors;

export interface FingerPrintProps {
  /**
      ### release(): (Android)
      Stops fingerprint scanner listener, releases cache of internal state in native code.
      - Returns a `void`

      -------------------
      Example
      
      ```
      componentWillUnmount() {
        FingerprintScanner.release();
      }
      ```
      */
  release: () => void;

  /**
        ### isSensorAvailable(): (Android, iOS)
        Checks if Fingerprint Scanner is able to be used by now.
        -  Returns a `Promise<Biometrics>`
        - `biometryType`: *String* - The type of biometric authentication supported by the device.
        - `error: FingerprintScannerError { name, message, biometric }` - The name and message of failure and the biometric type in use.
        
        -------------
        Example

        ```
          FingerprintScanner
            .isSensorAvailable()
            .then(biometryType => this.setState({ biometryType }))
            .catch(error => this.setState({ errorMessage: error.message }));
        ```

        ------------
      */
  isSensorAvailable: () => Promise<Biometrics>;

  /**
      ### authenticate({ description, fallbackEnabled }): (iOS) 

      - Returns a `Promise`
      - `description: String` - the string to explain the request for user authentication.
      - `fallbackEnabled: Boolean` - default to ***true***, whether to display fallback button (e.g. Enter Password).

      ----------------
      - Example: 
      ```
      FingerprintScanner
        .authenticate({ description: 'Scan your fingerprint on the device scanner to continue' })
        .then(() => {
          this.props.handlePopupDismissed();
          AlertIOS.alert('Authenticated successfully');
        })
        .catch((error) => {
          this.props.handlePopupDismissed();
          AlertIOS.alert(error.message);
        });
      ```
      -----------------

      ### authenticate({ description: 'Log in with Biometrics', onAttempt: () => (null) }): (Android)

      - Returns a `Promise`
      - `description: String` - the title text to appear on the native Android prompt
      - `onAttempt: Function` - a callback function when users are trying to scan their fingerprint but failed.

      -----------------
      - Example:
      ```
      FingerprintScanner
        .authenticate({
          description: 'Log in with Biometrics',
          onAttempt: this.handleAuthenticationAttempted,
        })
        .then(() => {
          this.props.handlePopupDismissed();
          Alert.alert('Fingerprint Authentication', 'Authenticated successfully');
        })
        .catch((error) => {
          this.setState({ errorMessage: error.message });
          this.description.shake();
        });
      ```
      -----------------
     */
  authenticate: (
    platformProps: AuthenticateIOS | AuthenticateAndroid
  ) => Promise<void>;
}

declare const FingerprintScanner: FingerPrintProps;

export default FingerprintScanner;
