import type { ColorValue, HostComponent, ViewProps } from 'react-native';
import type {
  DirectEventHandler,
  Double,
  Float,
  Int32,
  WithDefault,
} from 'react-native/Libraries/Types/CodegenTypes';
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';

type Event = Readonly<{
  result: string;
}>;

export interface NativeFormatConfigurations {
  _type?: string;
  regexFilter?: string;
  minimumSizeScore?: Double;
  addAdditionalQuietZone?: boolean;
  minimum1DQuietZoneSize?: Double;
  minimumTextLength?: Double;
  maximumTextLength?: Double;
  enableOneDBlurScanner?: boolean;
  returnStartEnd?: boolean;
  stripCheckDigits?: boolean;
  checksum?: boolean;
  code32?: boolean;
  code39?: boolean;
  pzn7?: boolean;
  pzn8?: boolean;
  tryCode39ExtendedMode?: boolean;
  useCode39CheckDigit?: boolean;
  gs1Handling?: string;
  iata2of5?: boolean;
  code25?: boolean;
  industrial2of5?: boolean;
  useIATA2OF5Checksum?: boolean;
  checksumAlgorithms?: string[];
  ean8?: boolean;
  ean13?: boolean;
  upca?: boolean;
  upce?: boolean;
  extensions?: string;
  minimumValue?: Double;
  allowNarrowBarsOnly?: boolean;
  allowWideBarsOnly?: boolean;
  strictMode?: boolean;
  qr?: boolean;
  microQr?: boolean;
  rmqr?: boolean;
  australiaPostCustomerFormat?: string;
  formats?: string[];
  minimumNumberOfRequiredFramesWithEqualRecognitionResult?: Double;
  minimumNumberOfRequiredFramesWithEqualRecognitionResultExtensionless?: Double;
  oneDConfirmationMode?: string;
}

export interface NativeBarcodeAccumulationConfiguration {
  accumulationTime?: WithDefault<Int32, 500>;
  removeUnconnectedResults?: WithDefault<boolean, true>;
  method?: WithDefault<string, 'INTERPOLATE_BY_CAMERA'>;
}

interface NativeProps extends ViewProps {
  onBarcodeScannerResult?: DirectEventHandler<Event>;
  onSelectBarcodeResult: DirectEventHandler<Event>;
  onError: DirectEventHandler<Readonly<{ message: string; code: Int32 }>>;
  flashEnabled?: WithDefault<boolean, false>;
  finderEnabled?: WithDefault<boolean, false>;
  finderStrokeWidth?: WithDefault<Int32, 2>;
  finderStrokeColor?: ColorValue;
  finderOverlayColor?: ColorValue;
  finderMinPadding?: WithDefault<Int32, 0>;
  finderInset?: {
    left?: WithDefault<Int32, 10>;
    top?: WithDefault<Int32, 10>;
    bottom?: WithDefault<Int32, 10>;
    right?: WithDefault<Int32, 10>;
  };
  finderRequiredAspectRatios?: {
    width?: WithDefault<Double, 4>;
    height?: WithDefault<Double, 3>;
  };
  cameraZoomFactor?: WithDefault<Float, 0.0>;
  cameraZoomRange?: {
    minZoom?: WithDefault<Float, 1.0>;
    maxZoom?: WithDefault<Float, 12.0>;
  };
  cameraModule?: WithDefault<string, 'BACK'>;
  hardwareButtonsEnabled?: WithDefault<boolean, true>;
  scanningEnabled?: WithDefault<boolean, true>;
  minFocusDistanceLock?: WithDefault<boolean, false>;
  overlayEnabled?: WithDefault<boolean, false>;
  overlayPolygonColor?: ColorValue;
  overlayStrokeColor?: ColorValue;
  overlayTextColor?: ColorValue;
  overlayTextContainerColor?: ColorValue;
  overlayTextFormat?: WithDefault<string, 'CODE_AND_TYPE'>;
  overlayLoadingTextValue?: WithDefault<string, undefined>;
  overlayBarcodeItemOverlayViewBinder?: WithDefault<boolean, false>;
  configFormatConfigurations?: Array<NativeFormatConfigurations>;
  configExtractedDocumentFormats?: Array<string>;
  configOnlyAcceptDocuments?: WithDefault<boolean, false>;
  configReturnBarcodeImage?: WithDefault<boolean, false>;
  configEngineMode?: WithDefault<string, 'NEXT_GEN'>;
  configAccumulation?: NativeBarcodeAccumulationConfiguration;
  configOptimizedForOverlays?: WithDefault<boolean, false>;
}

export default codegenNativeComponent<NativeProps>('ScanbotBarcodeScannerView');

interface NativeCommands {
  freezeCamera: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
  unfreezeCamera: (viewRef: React.ElementRef<HostComponent<NativeProps>>) => void;
  bindBarcodeItemOverlayView: (
    viewRef: React.ElementRef<HostComponent<NativeProps>>,
    barcodeItemUuid: string,
    bindingConfig: string
  ) => void;
}

export const Commands = codegenNativeCommands<NativeCommands>({
  supportedCommands: ['freezeCamera', 'unfreezeCamera', 'bindBarcodeItemOverlayView'],
});
