text: /* eslint-disable no-console */
  import React from 'react';
  import {
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
    Slider,
    TouchableWithoutFeedback,
    Dimensions,
  } from 'react-native';
  // eslint-disable-next-line import/no-unresolved
  import { RNCamera } from 'react-native-camera';
  
  const flashModeOrder = {
    off: 'on',
    on: 'auto',
    auto: 'torch',
    torch: 'off',
  };
  
  const wbOrder = {
    auto: 'sunny',
    sunny: 'cloudy',
    cloudy: 'shadow',
    shadow: 'fluorescent',
    fluorescent: 'incandescent',
    incandescent: 'auto',
  };
  
  const landmarkSize = 2;
  
  export default class CameraScreen extends React.Component {
    state = {
      flash: 'off',
      zoom: 0,
      autoFocus: 'on',
      autoFocusPoint: {
        normalized: { x: 0.5, y: 0.5 }, // normalized values required for autoFocusPointOfInterest
        drawRectPosition: {
          x: Dimensions.get('window').width * 0.5 - 32,
          y: Dimensions.get('window').height * 0.5 - 32,
        },
      },
      depth: 0,
      type: 'back',
      whiteBalance: 'auto',
      ratio: '16:9',
      recordOptions: {
        mute: false,
        maxDuration: 5,
        quality: RNCamera.Constants.VideoQuality['288p'],
      },
      isRecording: false,
      canDetectFaces: false,
      canDetectText: false,
      canDetectBarcode: false,
      faces: [],
      textBlocks: [],
      barcodes: [],
    };
  
    toggleFacing() {
      this.setState({
        type: this.state.type === 'back' ? 'front' : 'back',
      });
    }
  
    toggleFlash() {
      this.setState({
        flash: flashModeOrder[this.state.flash],
      });
    }
  
    toggleWB() {
      this.setState({
        whiteBalance: wbOrder[this.state.whiteBalance],
      });
    }
  
    toggleFocus() {
      this.setState({
        autoFocus: this.state.autoFocus === 'on' ? 'off' : 'on',
      });
    }
  
    touchToFocus(event) {
      const { pageX, pageY } = event.nativeEvent;
      const screenWidth = Dimensions.get('window').width;
      const screenHeight = Dimensions.get('window').height;
      const isPortrait = screenHeight > screenWidth;
  
      let x = pageX / screenWidth;
      let y = pageY / screenHeight;
      // Coordinate transform for portrait. See autoFocusPointOfInterest in docs for more info
      if (isPortrait) {
        x = pageY / screenHeight;
        y = -(pageX / screenWidth) + 1;
      }
  
      this.setState({
        autoFocusPoint: {
          normalized: { x, y },
          drawRectPosition: { x: pageX, y: pageY },
        },
      });
    }
  
    zoomOut() {
      this.setState({
        zoom: this.state.zoom - 0.1 < 0 ? 0 : this.state.zoom - 0.1,
      });
    }
  
    zoomIn() {
      this.setState({
        zoom: this.state.zoom + 0.1 > 1 ? 1 : this.state.zoom + 0.1,
      });
    }
  
    setFocusDepth(depth) {
      this.setState({
        depth,
      });
    }
  
    takePicture = async function() {
      if (this.camera) {
        const data = await this.camera.takePictureAsync();
        console.warn('takePicture ', data);
      }
    };
  
    takeVideo = async function() {
      if (this.camera) {
        try {
          const promise = this.camera.recordAsync(this.state.recordOptions);
  
          if (promise) {
            this.setState({ isRecording: true });
            const data = await promise;
            this.setState({ isRecording: false });
            console.warn('takeVideo', data);
          }
        } catch (e) {
          console.error(e);
        }
      }
    };
  
    toggle = value => () => this.setState(prevState => ({ [value]: !prevState[value] }));
  
    facesDetected = ({ faces }) => this.setState({ faces });
  
    renderFace = ({ bounds, faceID, rollAngle, yawAngle }) => (
      <View
        key={faceID}
        transform={[
          { perspective: 600 },
          { rotateZ: `${rollAngle.toFixed(0)}deg` },
          { rotateY: `${yawAngle.toFixed(0)}deg` },
        ]}
        style={[
          styles.face,
          {
            ...bounds.size,
            left: bounds.origin.x,
            top: bounds.origin.y,
          },
        ]}
      >
        <Text style={styles.faceText}>ID: {faceID}</Text>
        <Text style={styles.faceText}>rollAngle: {rollAngle.toFixed(0)}</Text>
        <Text style={styles.faceText}>yawAngle: {yawAngle.toFixed(0)}</Text>
      </View>
    );
  
    renderLandmarksOfFace(face) {
      const renderLandmark = position =>
        position && (
          <View
            style={[
              styles.landmark,
              {
                left: position.x - landmarkSize / 2,
                top: position.y - landmarkSize / 2,
              },
            ]}
          />
        );
      return (
        <View key={`landmarks-${face.faceID}`}>
          {renderLandmark(face.leftEyePosition)}
          {renderLandmark(face.rightEyePosition)}
          {renderLandmark(face.leftEarPosition)}
          {renderLandmark(face.rightEarPosition)}
          {renderLandmark(face.leftCheekPosition)}
          {renderLandmark(face.rightCheekPosition)}
          {renderLandmark(face.leftMouthPosition)}
          {renderLandmark(face.mouthPosition)}
          {renderLandmark(face.rightMouthPosition)}
          {renderLandmark(face.noseBasePosition)}
          {renderLandmark(face.bottomMouthPosition)}
        </View>
      );
    }
  
    renderFaces = () => (
      <View style={styles.facesContainer} pointerEvents="none">
        {this.state.faces.map(this.renderFace)}
      </View>
    );
  
    renderLandmarks = () => (
      <View style={styles.facesContainer} pointerEvents="none">
        {this.state.faces.map(this.renderLandmarksOfFace)}
      </View>
    );
  
    renderTextBlocks = () => (
      <View style={styles.facesContainer} pointerEvents="none">
        {this.state.textBlocks.map(this.renderTextBlock)}
      </View>
    );
  
    renderTextBlock = ({ bounds, value }) => (
      <React.Fragment key={value + bounds.origin.x}>
        <Text style={[styles.textBlock, { left: bounds.origin.x, top: bounds.origin.y }]}>
          {value}
        </Text>
        <View
          style={[
            styles.text,
            {
              ...bounds.size,
              left: bounds.origin.x,
              top: bounds.origin.y,
            },
          ]}
        />
      </React.Fragment>
    );
  
    textRecognized = object => {
      const { textBlocks } = object;
      this.setState({ textBlocks });
    };
  
    barcodeRecognized = ({ barcodes }) => this.setState({ barcodes });
  
    renderBarcodes = () => (
      <View style={styles.facesContainer} pointerEvents="none">
        {this.state.barcodes.map(this.renderBarcode)}
      </View>
    );
  
    renderBarcode = ({ bounds, data, type }) => (
      <React.Fragment key={data + bounds.origin.x}>
        <View
          style={[
            styles.text,
            {
              ...bounds.size,
              left: bounds.origin.x,
              top: bounds.origin.y,
            },
          ]}
        >
          <Text style={[styles.textBlock]}>{`${data} ${type}`}</Text>
        </View>
      </React.Fragment>
    );
  
    renderCamera() {
      const { canDetectFaces, canDetectText, canDetectBarcode } = this.state;
  
      const drawFocusRingPosition = {
        top: this.state.autoFocusPoint.drawRectPosition.y - 32,
        left: this.state.autoFocusPoint.drawRectPosition.x - 32,
      };
      return (
        <RNCamera
          ref={ref => {
            this.camera = ref;
          }}
          style={{
            flex: 1,
            justifyContent: 'space-between',
          }}
          type={this.state.type}
          flashMode={this.state.flash}
          autoFocus={this.state.autoFocus}
          autoFocusPointOfInterest={this.state.autoFocusPoint.normalized}
          zoom={this.state.zoom}
          whiteBalance={this.state.whiteBalance}
          ratio={this.state.ratio}
          focusDepth={this.state.depth}
          androidCameraPermissionOptions={{
            title: 'Permission to use camera',
            message: 'We need your permission to use your camera',
            buttonPositive: 'Ok',
            buttonNegative: 'Cancel',
          }}
          faceDetectionLandmarks={
            RNCamera.Constants.FaceDetection.Landmarks
              ? RNCamera.Constants.FaceDetection.Landmarks.all
              : undefined
          }
          onFacesDetected={canDetectFaces ? this.facesDetected : null}
          onTextRecognized={canDetectText ? this.textRecognized : null}
          onGoogleVisionBarcodesDetected={canDetectBarcode ? this.barcodeRecognized : null}
        >
          <View style={StyleSheet.absoluteFill}>
            <View style={[styles.autoFocusBox, drawFocusRingPosition]} />
            <TouchableWithoutFeedback onPress={this.touchToFocus.bind(this)}>
              <View style={{ flex: 1 }} />
            </TouchableWithoutFeedback>
          </View>
          <View
            style={{
              flex: 0.5,
              height: 72,
              backgroundColor: 'transparent',
              flexDirection: 'row',
              justifyContent: 'space-around',
            }}
          >
            <View
              style={{
                backgroundColor: 'transparent',
                flexDirection: 'row',
                justifyContent: 'space-around',
              }}
            >
              <TouchableOpacity style={styles.flipButton} onPress={this.toggleFacing.bind(this)}>
                <Text style={styles.flipText}> FLIP </Text>
              </TouchableOpacity>
              <TouchableOpacity style={styles.flipButton} onPress={this.toggleFlash.bind(this)}>
                <Text style={styles.flipText}> FLASH: {this.state.flash} </Text>
              </TouchableOpacity>
              <TouchableOpacity style={styles.flipButton} onPress={this.toggleWB.bind(this)}>
                <Text style={styles.flipText}> WB: {this.state.whiteBalance} </Text>
              </TouchableOpacity>
            </View>
            <View
              style={{
                backgroundColor: 'transparent',
                flexDirection: 'row',
                justifyContent: 'space-around',
              }}
            >
              <TouchableOpacity onPress={this.toggle('canDetectFaces')} style={styles.flipButton}>
                <Text style={styles.flipText}>
                  {!canDetectFaces ? 'Detect Faces' : 'Detecting Faces'}
                </Text>
              </TouchableOpacity>
              <TouchableOpacity onPress={this.toggle('canDetectText')} style={styles.flipButton}>
                <Text style={styles.flipText}>
                  {!canDetectText ? 'Detect Text' : 'Detecting Text'}
                </Text>
              </TouchableOpacity>
              <TouchableOpacity onPress={this.toggle('canDetectBarcode')} style={styles.flipButton}>
                <Text style={styles.flipText}>
                  {!canDetectBarcode ? 'Detect Barcode' : 'Detecting Barcode'}
                </Text>
              </TouchableOpacity>
            </View>
          </View>
          <View style={{ bottom: 0 }}>
            <View
              style={{
                height: 20,
                backgroundColor: 'transparent',
                flexDirection: 'row',
                alignSelf: 'flex-end',
              }}
            >
              <Slider
                style={{ width: 150, marginTop: 15, alignSelf: 'flex-end' }}
                onValueChange={this.setFocusDepth.bind(this)}
                step={0.1}
                disabled={this.state.autoFocus === 'on'}
              />
            </View>
            <View
              style={{
                height: 56,
                backgroundColor: 'transparent',
                flexDirection: 'row',
                alignSelf: 'flex-end',
              }}
            >
              <TouchableOpacity
                style={[
                  styles.flipButton,
                  {
                    flex: 0.3,
                    alignSelf: 'flex-end',
                    backgroundColor: this.state.isRecording ? 'white' : 'darkred',
                  },
                ]}
                onPress={this.state.isRecording ? () => {} : this.takeVideo.bind(this)}
              >
                {this.state.isRecording ? (
                  <Text style={styles.flipText}> ☕ </Text>
                ) : (
                  <Text style={styles.flipText}> REC </Text>
                )}
              </TouchableOpacity>
            </View>
            {this.state.zoom !== 0 && (
              <Text style={[styles.flipText, styles.zoomText]}>Zoom: {this.state.zoom}</Text>
            )}
            <View
              style={{
                height: 56,
                backgroundColor: 'transparent',
                flexDirection: 'row',
                alignSelf: 'flex-end',
              }}
            >
              <TouchableOpacity
                style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
                onPress={this.zoomIn.bind(this)}
              >
                <Text style={styles.flipText}> + </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={[styles.flipButton, { flex: 0.1, alignSelf: 'flex-end' }]}
                onPress={this.zoomOut.bind(this)}
              >
                <Text style={styles.flipText}> - </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={[styles.flipButton, { flex: 0.25, alignSelf: 'flex-end' }]}
                onPress={this.toggleFocus.bind(this)}
              >
                <Text style={styles.flipText}> AF : {this.state.autoFocus} </Text>
              </TouchableOpacity>
              <TouchableOpacity
                style={[styles.flipButton, styles.picButton, { flex: 0.3, alignSelf: 'flex-end' }]}
                onPress={this.takePicture.bind(this)}
              >
                <Text style={styles.flipText}> SNAP </Text>
              </TouchableOpacity>
            </View>
          </View>
          {!!canDetectFaces && this.renderFaces()}
          {!!canDetectFaces && this.renderLandmarks()}
          {!!canDetectText && this.renderTextBlocks()}
          {!!canDetectBarcode && this.renderBarcodes()}
        </RNCamera>
      );
    }
  
    render() {
      return <View style={styles.container}>{this.renderCamera()}</View>;
    }
  }
  
  const styles = StyleSheet.create({
    container: {
      flex: 1,
      paddingTop: 10,
      backgroundColor: '#000',
    },
    flipButton: {
      flex: 0.3,
      height: 40,
      marginHorizontal: 2,
      marginBottom: 10,
      marginTop: 10,
      borderRadius: 8,
      borderColor: 'white',
      borderWidth: 1,
      padding: 5,
      alignItems: 'center',
      justifyContent: 'center',
    },
    autoFocusBox: {
      position: 'absolute',
      height: 64,
      width: 64,
      borderRadius: 12,
      borderWidth: 2,
      borderColor: 'white',
      opacity: 0.4,
    },
    flipText: {
      color: 'white',
      fontSize: 15,
    },
    zoomText: {
      position: 'absolute',
      bottom: 70,
      zIndex: 2,
      left: 2,
    },
    picButton: {
      backgroundColor: 'darkseagreen',
    },
    facesContainer: {
      position: 'absolute',
      bottom: 0,
      right: 0,
      left: 0,
      top: 0,
    },
    face: {
      padding: 10,
      borderWidth: 2,
      borderRadius: 2,
      position: 'absolute',
      borderColor: '#FFD700',
      justifyContent: 'center',
      backgroundColor: 'rgba(0, 0, 0, 0.5)',
    },
    landmark: {
      width: landmarkSize,
      height: landmarkSize,
      position: 'absolute',
      backgroundColor: 'red',
    },
    faceText: {
      color: '#FFD700',
      fontWeight: 'bold',
      textAlign: 'center',
      margin: 10,
      backgroundColor: 'transparent',
    },
    text: {
      padding: 10,
      borderWidth: 2,
      borderRadius: 2,
      position: 'absolute',
      borderColor: '#F00',
      justifyContent: 'center',
    },
    textBlock: {
      color: '#F00',
      position: 'absolute',
      textAlign: 'center',
      backgroundColor: 'transparent',
    },
  });
  