import * as React from 'react';
import { View, Dimensions } from 'react-native';
import { RNCamera } from 'react-native-camera';

import {
  CAMERA_MASK_HOLE_HEIGHT,
  CAMERA_MASK_HOLE_MARGIN,
  DEFAULT_CAMERA_BARCODE_READ_TIMEOUT,
} from '~/config';
import { testIdProps } from '~/test/utils';

import { ChildComponentProps } from './scanner.props';
import { scannerCameraStyles as styles } from './scanner.styles';

const CAMERA_VIEW_HEIGHT = Dimensions.get('window').height;
const CAMERA_VIEW_WIDTH = Dimensions.get('window').width;

// https://github.com/react-native-community/react-native-camera/pull/2719/files
// https://medium.com/@jameswang1019/how-to-limit-code-scan-area-with-react-native-camera-android-and-ios-ba5e1de78155
// A quick tip of implementing on IOS is that the x, y, width, height props
// to be provided to the rectOfInterest prop are normalized coordinates
// from (0,0) the top left corner to (1,1) the bottom right corner of the camera view
// in landscape orientation with the home button on the right.
const topMargin = CAMERA_MASK_HOLE_MARGIN / 2;
const leftMargin = CAMERA_VIEW_HEIGHT / 2 - CAMERA_MASK_HOLE_MARGIN - CAMERA_MASK_HOLE_HEIGHT / 2;
const frameWidth = CAMERA_MASK_HOLE_HEIGHT + CAMERA_MASK_HOLE_MARGIN;
const frameHeight = CAMERA_VIEW_WIDTH - CAMERA_MASK_HOLE_MARGIN;
const scanAreaX = leftMargin / CAMERA_VIEW_HEIGHT;
const scanAreaY = topMargin / CAMERA_VIEW_WIDTH;
const scanAreaWidth = frameWidth / CAMERA_VIEW_HEIGHT;
const scanAreaHeight = frameHeight / CAMERA_VIEW_WIDTH;
const rectOfInterest = {
  x: scanAreaX,
  y: scanAreaY,
  width: scanAreaWidth,
  height: scanAreaHeight,
};

/**
 * Component in charge to detect a Barcode
 * @param onBarcodeDetected Callback executed when the device detects a barcode
 * @param style An optional style override useful for padding & margin.
 */
export function ScannerCamera(props: ChildComponentProps) {
  const { cameraBarcodeReadTimeout, flashlight, onBarcodeDetected, ...rest } = props;
  const [enabled, setEnabled] = React.useState(true);

  return (
    <View style={styles.container}>
      <RNCamera
        {...{ rectOfInterest }}
        androidCameraPermissionOptions={{
          title: 'Permission to use camera',
          message: 'We need your permission to use your camera',
          buttonPositive: 'Ok',
          buttonNegative: 'Cancel',
        }}
        barCodeTypes={[RNCamera.Constants.BarCodeType.code128]}
        cameraViewDimensions={{ width: CAMERA_VIEW_WIDTH, height: CAMERA_VIEW_HEIGHT }}
        captureAudio={false}
        flashMode={flashlight ? RNCamera.Constants.FlashMode.torch : null}
        style={styles.preview}
        type={RNCamera.Constants.Type.back}
        onBarCodeRead={(barcode) => {
          if (enabled) {
            setEnabled(false);
            onBarcodeDetected(barcode.data);
            setTimeout(() => {
              setEnabled(true);
            }, cameraBarcodeReadTimeout);
          }
        }}
        {...rest}
        {...testIdProps('react-native-camera')}
      />
    </View>
  );
}

ScannerCamera.defaultProps = {
  cameraBarcodeReadTimeout: DEFAULT_CAMERA_BARCODE_READ_TIMEOUT,
};
