import {
  copyAssetsFileIOS,
  copyFile,
  ExternalDirectoryPath,
  TemporaryDirectoryPath,
} from "@dr.pogodin/react-native-fs";
import { CameraRoll } from "@react-native-camera-roll/camera-roll";
import React from "react";
import { Platform, View } from "react-native";

const mockFrame = {
  isValid: true,
  width: 1920,
  height: 1080,
  bytesPerRow: 1920,
  planesCount: 1,
  isMirrored: false,
  timestamp: 0,
  orientation: "portrait",
  pixelFormat: "yuv",
  // Returns a fake ArrayBuffer
  toArrayBuffer: () => new ArrayBuffer( 1920 * 1080 ),
  toString: () => "Frame",
  getNativeBuffer: () => ( {
    // Returns a fake pointer
    pointer: 0,
    delete: () => null,
  } ),
  incrementRefCount: () => null,
  decrementRefCount: () => null,
};

const style = { flex: 1, backgroundColor: "red" };
export class mockCamera extends React.PureComponent {
  static async getAvailableCameraDevices() {
    return [
      {
        position: "back",
      },
    ];
  }

  /*
    Every time the component updates we are running the frame processor that is a prop
    to the camera component. We are running the frame processor with a mocked frame that
    does not include any kind of image data at all.
    Running it only on component update means it only is called a few times and not
    every second (or so - depending on fps). This is enough to satisfy the e2e test
    though because the mocked prediction needs to appear only once to be found by the
    test matcher. I tried running it with a timer every second but since it never idles
    the test never finishes.
  */
  componentDidUpdate() {
    const { frameProcessor, isActive } = this.props;
    if ( isActive === false || !frameProcessor ) {
      return;
    }
    frameProcessor.frameProcessor( mockFrame );
  }

  // eslint-disable-next-line class-methods-use-this, react/no-unused-class-component-methods
  async takePhoto() {
    if ( Platform.OS === "android" ) {
      /*
        On Android, copyAssetsFileIOS is not available. Instead, copy the test
        image that was pushed to the app's external files directory by
        iNatE2eBeforeAll (via `adb push e2e/animal.jpg`).
        ExternalDirectoryPath = /sdcard/Android/data/<package>/files/
        which is accessible by the app without extra permissions.
      */
      const sourcePath = `${ExternalDirectoryPath}/e2e_test.jpg`;
      const destPath = `${TemporaryDirectoryPath}/temp.jpg`;
      try {
        await copyFile( sourcePath, destPath );
        return {
          path: destPath,
          metadata: { Orientation: 1 },
        };
      } catch ( err ) {
        console.log( "Error copying test photo on Android:", err );
        return null;
      }
    }

    return CameraRoll.getPhotos( {
      first: 20,
      assetType: "Photos",
    } )
      .then( async r => {
        /*
          Basically, here, we are reading the newest twenty photos from the simulators gallery
          and return the oldest one of those. Copy it to a new path and treat it as a new photo.
        */
        const testPhoto = r.edges[r.edges.length - 1].node.image;
        let oldUri = testPhoto.uri;
        if ( testPhoto.uri.includes( "ph://" ) ) {
          let id = testPhoto.uri.replace( "ph://", "" );
          id = id.substring( 0, id.indexOf( "/" ) );
          oldUri = `assets-library://asset/asset.jpg?id=${id}&ext=jpg`;
          console.log( `Converted file uri to ${oldUri}` );
        }
        const encodedUri = encodeURI( oldUri );
        const destPath = `${TemporaryDirectoryPath}/temp.jpg`;
        const newPath = await copyAssetsFileIOS(
          encodedUri,
          destPath,
          0,
          0,
        );
        const photo = { uri: newPath, predictions: [] };
        if ( typeof photo !== "object" ) {
          console.log( "photo is not an object", typeof photo );
          return null;
        }
        return {
          ...testPhoto,
          path: newPath,
          metadata: {
            Orientation: testPhoto.orientation,
          },
        };
      } )
      .catch( err => {
        console.log( "Error getting photos", err );
        return null;
      } );
  }

  render() {
    return <View style={style} collapsable={false} />;
  }
}

export const mockSortDevices = ( _left, _right ) => 1;

const device = {
  physicalDevices: ["wide-angle-camera"],
  hasFlash: true,
  hasTorch: true,
  id: "1",
  isMultiCam: true,
  maxZoom: 12.931958198547363,
  minZoom: 1,
  name: "front (1)",
  neutralZoom: 1,
  position: "front",
  supportsDepthCapture: false,
  supportsFocus: true,
  supportsLowLightBoost: false,
  supportsParallelVideoProcessing: true,
  supportsRawCapture: true,
};

export const mockUseCameraDevice = _deviceType => device;
export const mockUseCameraDevices = () => [device];

export const mockUseCameraFormat = _device => {
  const format = {
    autoFocusSystem: "contrast-detection",
    fieldOfView: 83.97117848314457,
    maxFps: 60,
    maxISO: 11377,
    minFps: 15,
    minISO: 44,
    photoHeight: 3024,
    photoWidth: 4032,
    pixelFormats: ["yuv", "native"],
    supportsDepthCapture: false,
    supportsPhotoHdr: false,
    supportsVideoHdr: false,
    videoHeight: 2160,
    videoStabilizationModes: ["off", "cinematic", "cinematic-extended"],
    videoWidth: 3840,
  };
  return format;
};
