import type { Image } from 'react-native-nitro-image';
import type { TargetPhotoContainerFormat } from '../common-types/PhotoContainerFormat';
import type { QualityPrioritization } from '../common-types/QualityPrioritization';
import type { Size } from '../common-types/Size';
import type { Photo } from '../instances/Photo.nitro';
import type { Location } from '../location/Location.nitro';
import type { CameraOutput } from './CameraOutput.nitro';
/**
 * Configuration options for a {@linkcode CameraPhotoOutput}.
 *
 * @see {@linkcode CameraPhotoOutput}
 * @see {@linkcode usePhotoOutput | usePhotoOutput(...)}
 */
export interface PhotoOutputOptions {
    /**
     * The target Photo Resolution to use.
     *
     * @discussion
     * The {@linkcode CameraSession} will negotiate all
     * output {@linkcode targetResolution}s and constraints (such
     * as HDR, FPS, etc) in a {@linkcode CameraSessionConfig} to
     * finalize the Resolution used for the Output.
     * This is therefore merely a resolution _target_, and may
     * not be exactly met.
     *
     * If the given {@linkcode targetResolution} cannot be met
     * exactly, its aspect ratio (computed by
     * {@linkcode Size.width} / {@linkcode Size.height}) will
     * be prioritized over pixel count.
     */
    targetResolution: Size;
    /**
     * Specifies the {@linkcode TargetPhotoContainerFormat} to
     * shoot the {@linkcode Photo} in.
     */
    containerFormat: TargetPhotoContainerFormat;
    /**
     * Defines the compression quality for processed photo formats.
     *
     * The value must be within the normalized range from `0.0` to `1.0`,
     * where `1.0` is the highest quality and `0.0` is the strongest compression.
     *
     * RAW photo formats such as {@linkcode TargetPhotoContainerFormat | 'dng'}
     * ignore this option.
     *
     * @default 0.9 in {@linkcode usePhotoOutput | usePhotoOutput(...)}
     */
    quality: number;
    /**
     * Specifies the balance between speed or image quality for
     * the photo capture pipeline.
     *
     * The currently selected {@linkcode CameraDevice} must support
     * {@linkcode QualityPrioritization} {@linkcode QualityPrioritization | 'speed'}
     * (see {@linkcode CameraDevice.supportsSpeedQualityPrioritization | supportsSpeedQualityPrioritization}),
     * otherwise an error will be thrown.
     *
     * @see {@linkcode CameraDevice.supportsSpeedQualityPrioritization}
     */
    qualityPrioritization: QualityPrioritization;
    /**
     * When this is set to a specific {@linkcode Size},
     * a ready to display {@linkcode Image} will be delivered
     * just before the resulting {@linkcode Photo} is available.
     *
     * Preview Image delivery requires additional processing,
     * so this is disabled by default.
     *
     * If this is `undefined` (the default), no preview Image
     * will be supplied.
     *
     * It is recommended to set this to a {@linkcode Size}
     * that is as low as possible to avoid unnecessary overhead.
     *
     * @see {@linkcode CapturePhotoCallbacks.onPreviewImageAvailable}
     * @default undefined
     */
    previewImageTargetSize?: Size;
}
/**
 * Callbacks for a {@linkcode CameraPhotoOutput.capturePhoto | capturePhoto(...)}
 * call.
 *
 * @see {@linkcode CameraPhotoOutput}
 */
export interface CapturePhotoCallbacks {
    /**
     * Called when the pipeline starts
     * the capture.
     */
    onWillBeginCapture?: () => void;
    /**
     * Called just before the pipeline
     * starts capturing the photo.
     */
    onWillCapturePhoto?: () => void;
    /**
     * Called just after the pipeline
     * captured a photo.
     */
    onDidCapturePhoto?: () => void;
    /**
     * Called just after {@linkcode onWillBeginCapture}
     * with an {@linkcode Image} suitable for preview
     * or thumbnail updates.
     *
     * This will only be called if a preview image
     * size is set via {@linkcode PhotoOutputOptions.previewImageTargetSize},
     * and the {@linkcode CameraDevice} supports preview
     * images (see {@linkcode CameraDevice.supportsPreviewImage}).
     */
    onPreviewImageAvailable?: (previewImage: Image) => void;
}
/**
 * Configures flash for photo capture.
 *
 * @see {@linkcode CameraPhotoOutput.capturePhoto | capturePhoto(...)}
 */
export type FlashMode = 'off' | 'on' | 'auto';
/**
 * Configuration options for a
 * {@linkcode CameraPhotoOutput.capturePhoto | capturePhoto(...)} call.
 *
 * @see {@linkcode CameraPhotoOutput}
 */
export interface CapturePhotoSettings {
    /**
     * Configures the {@linkcode FlashMode} for this Photo
     * capture.
     *
     * @throws If {@linkcode FlashMode} is `'on'`, but
     * the {@linkcode CameraDevice} does not have a
     * flash - see {@linkcode CameraDevice.hasFlash}
     * @default 'off'
     */
    flashMode?: FlashMode;
    /**
     * Enables or disables the system shutter sound.
     * The shutter sound is fired exactly when a photo will be captured.
     *
     * The OS may choose to override this behaviour, e.g. if
     * regional sound-suppression settings are applied.
     *
     * @default true
     */
    enableShutterSound?: boolean;
    /**
     * Enables or disables depth data delivery in the resulting
     * {@linkcode Photo}.
     *
     * Depth data will be embedded in the Photo and can be accessed
     * via {@linkcode Photo.depth}.
     *
     * {@linkcode enableDepthData} can only be enabled if the
     * {@linkcode CameraPhotoOutput} supports depth data - see
     * {@linkcode CameraPhotoOutput.supportsDepthDataDelivery}.
     *
     * @default false
     */
    enableDepthData?: boolean;
    /**
     * Specifies whether red-eye reduction should be applied
     * automatically on flash captures.
     *
     * When {@linkcode flashMode} is {@linkcode FlashMode | 'off'},
     * red eye reduction is automataically disabled.
     *
     * @default true
     */
    enableRedEyeReduction?: boolean;
    /**
     * Specifies whether the capture pipeline should
     * deliver Camera calibration data.
     *
     * A {@linkcode Photo}'s calibration data can be accessed via
     * {@linkcode Photo.calibrationData | Photo.calibrationData}.
     *
     * @platform iOS
     * @default false
     */
    enableCameraCalibrationDataDelivery?: boolean;
    /**
     * Specifies whether the capture pipeline should
     * automatically correct lens distortion.
     *
     * @note If enabled, captured photos will look
     * slightly different compared to the Preview
     * because the field-of-view might be narrower.
     *
     * @default false
     */
    enableDistortionCorrection?: boolean;
    /**
     * Enables or disables virtual device image fusion.
     *
     * If enabled, the Camera pipeline may capture photos
     * from multiple constituent physical Camera devices at once
     * (if using a Camera device that has multiple physical devices)
     * to improve still image quality.
     *
     * When capturing RAW photos, this is disabled.
     *
     * @default true
     */
    enableVirtualDeviceFusion?: boolean;
    /**
     * Sets the given {@linkcode Location} to be embedded
     * into the EXIF data of the captured {@linkcode Photo}.
     *
     * @default undefined
     */
    location?: Location;
}
/**
 * Represents a Photo written to a File.
 */
export interface PhotoFile {
    /**
     * The path of the file.
     * This is a filesystem path, not a `file://` URL.
     */
    filePath: string;
}
/**
 * The {@linkcode CameraPhotoOutput} allows capturing {@linkcode Photo}s
 * in-memory, as well as directly to a file.
 *
 * In-memory {@linkcode Photo}s can be converted to Images for immediate
 * display, and/or saved to a file (or the media gallery) later on.
 *
 * @see {@linkcode PhotoOutputOptions}
 * @see {@linkcode CapturePhotoSettings}
 * @see {@linkcode usePhotoOutput | usePhotoOutput(...)}
 * @example
 * Creating a `CameraPhotoOutput` via the Hooks API:
 * ```ts
 * const photoOutput = usePhotoOutput()
 * ```
 *
 * @example
 * Creating a `CameraPhotoOutput` via the Imperative API:
 * ```ts
 * const photoOutput = VisionCamera.createPhotoOutput({
 *   targetResolution: CommonResolutions.UHD_4_3,
 *   containerFormat: 'native',
 *   quality: 0.9,
 *   qualityPrioritization: 'balanced',
 * })
 * ```
 */
export interface CameraPhotoOutput extends CameraOutput {
    /**
     * Get whether this {@linkcode CameraPhotoOutput} supports
     * capturing depth data alongside with a normal {@linkcode Photo},
     * e.g. for portrait effects matte.
     * @see {@linkcode CapturePhotoSettings.enableDepthData}
     */
    readonly supportsDepthDataDelivery: boolean;
    /**
     * get whether this {@linkcode CameraPhotoOutput} supports
     * delivering camera calibration data, e.g. for reconstructing
     * lens-distortion or geometry.
     * @see {@linkcode CapturePhotoSettings.enableCameraCalibrationDataDelivery}
     */
    readonly supportsCameraCalibrationDataDelivery: boolean;
    /**
     * Captures a {@linkcode Photo} using the given
     * {@linkcode CapturePhotoSettings}.
     *
     * @note
     * On Android, it is recommended to use
     * {@linkcode capturePhoto | capturePhoto(...)} only
     * for {@linkcode TargetPhotoContainerFormat | 'jpeg'} images, and use
     * {@linkcode capturePhotoToFile | capturePhotoToFile(...)}
     * for any other formats (such as RAW ({@linkcode TargetPhotoContainerFormat | 'dng'}),
     * as CameraX does not properly support in-memory Photos for formats like RAW yet.
     * See https://issuetracker.google.com/u/3/issues/482079661 for more information.
     *
     * @note
     * The {@linkcode Photo} has to be `dispose()`'d after it
     * is no longer used, as otherwise the JS Runtime might not
     * immediately delete it, possibly exhausting system resources.
     *
     * @example
     * ```ts
     * const photo = await photoOutput.capturePhoto(
     *   { flashMode: 'on' },
     *   {}
     * )
     * // ...
     * photo.dispose()
     * ```
     */
    capturePhoto(settings: CapturePhotoSettings, callbacks: CapturePhotoCallbacks): Promise<Photo>;
    /**
     * Captures a Photo and writes it to a temporary file
     * using the given {@linkcode CapturePhotoSettings}.
     * @example
     * ```ts
     * const photoFile = await photoOutput.capturePhotoToFile(
     *   { flashMode: 'on' },
     *   {}
     * )
     * ```
     */
    capturePhotoToFile(settings: CapturePhotoSettings, callbacks: CapturePhotoCallbacks): Promise<PhotoFile>;
    /**
     * Asynchronously prepares the {@linkcode CameraPhotoOutput}
     * with the given {@linkcode settings} array to improve capture
     * responsiveness for subsequent {@linkcode capturePhoto | capturePhoto(...)}
     * calls when called with any of the same {@linkcode CapturePhotoSettings}
     * that have been prepared via this method.
     *
     * @discussion
     * It is recommended to always call this with a few common
     * settings you expect to be used for {@linkcode capturePhoto | capturePhoto(...)}
     * later on.
     *
     * It is perfectly fine to not call {@linkcode prepareSettings | prepareSettings(...)}
     * when using Photo capture, but {@linkcode capturePhoto | capturePhoto(...)} may
     * allocate buffers that cause higher latency on initial calls when aiming for quality.
     *
     * On Android, this method is no-op.
     *
     * @example
     * ```ts
     * const photoOutput = usePhotoOutput({})
     *
     * useEffect(() => {
     *   photoOutput.prepareSettings([
     *     { flashMode: 'off', enableDistortionCorrection: true },
     *     { flashMode: 'on', enableDistortionCorrection: false },
     *   ])
     * }, [])
     * ```
     */
    prepareSettings(settings: CapturePhotoSettings[]): Promise<void>;
}
