// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.plugins.camera;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.Activity;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
import android.os.Build;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.systemchannels.PlatformChannel;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.camera.features.CameraFeatureFactory;
import io.flutter.plugins.camera.features.Point;
import io.flutter.plugins.camera.features.autofocus.AutoFocusFeature;
import io.flutter.plugins.camera.features.autofocus.FocusMode;
import io.flutter.plugins.camera.features.exposurelock.ExposureLockFeature;
import io.flutter.plugins.camera.features.exposurelock.ExposureMode;
import io.flutter.plugins.camera.features.exposureoffset.ExposureOffsetFeature;
import io.flutter.plugins.camera.features.exposurepoint.ExposurePointFeature;
import io.flutter.plugins.camera.features.flash.FlashFeature;
import io.flutter.plugins.camera.features.flash.FlashMode;
import io.flutter.plugins.camera.features.focuspoint.FocusPointFeature;
import io.flutter.plugins.camera.features.fpsrange.FpsRangeFeature;
import io.flutter.plugins.camera.features.noisereduction.NoiseReductionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionFeature;
import io.flutter.plugins.camera.features.resolution.ResolutionPreset;
import io.flutter.plugins.camera.features.sensororientation.DeviceOrientationManager;
import io.flutter.plugins.camera.features.sensororientation.SensorOrientationFeature;
import io.flutter.plugins.camera.features.zoomlevel.ZoomLevelFeature;
import io.flutter.plugins.camera.utils.TestUtils;
import io.flutter.view.TextureRegistry;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CameraTest {
  private CameraProperties mockCameraProperties;
  private CameraFeatureFactory mockCameraFeatureFactory;
  private DartMessenger mockDartMessenger;
  private Camera camera;
  private CameraCaptureSession mockCaptureSession;
  private CaptureRequest.Builder mockPreviewRequestBuilder;

  @Before
  public void before() {
    mockCameraProperties = mock(CameraProperties.class);
    mockCameraFeatureFactory = new TestCameraFeatureFactory();
    mockDartMessenger = mock(DartMessenger.class);
    mockCaptureSession = mock(CameraCaptureSession.class);
    mockPreviewRequestBuilder = mock(CaptureRequest.Builder.class);

    final Activity mockActivity = mock(Activity.class);
    final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
        mock(TextureRegistry.SurfaceTextureEntry.class);
    final String cameraName = "1";
    final ResolutionPreset resolutionPreset = ResolutionPreset.high;
    final boolean enableAudio = false;

    when(mockCameraProperties.getCameraName()).thenReturn(cameraName);

    camera =
        new Camera(
            mockActivity,
            mockFlutterTexture,
            mockCameraFeatureFactory,
            mockDartMessenger,
            mockCameraProperties,
            resolutionPreset,
            enableAudio);

    TestUtils.setPrivateField(camera, "captureSession", mockCaptureSession);
    TestUtils.setPrivateField(camera, "previewRequestBuilder", mockPreviewRequestBuilder);
  }

  @After
  public void after() {
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 0);
  }

  @Test
  public void shouldCreateCameraPluginAndSetAllFeatures() {
    final Activity mockActivity = mock(Activity.class);
    final TextureRegistry.SurfaceTextureEntry mockFlutterTexture =
        mock(TextureRegistry.SurfaceTextureEntry.class);
    final CameraFeatureFactory mockCameraFeatureFactory = mock(CameraFeatureFactory.class);
    final String cameraName = "1";
    final ResolutionPreset resolutionPreset = ResolutionPreset.high;
    final boolean enableAudio = false;

    when(mockCameraProperties.getCameraName()).thenReturn(cameraName);
    SensorOrientationFeature mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
    when(mockCameraFeatureFactory.createSensorOrientationFeature(any(), any(), any()))
        .thenReturn(mockSensorOrientationFeature);

    Camera camera =
        new Camera(
            mockActivity,
            mockFlutterTexture,
            mockCameraFeatureFactory,
            mockDartMessenger,
            mockCameraProperties,
            resolutionPreset,
            enableAudio);

    verify(mockCameraFeatureFactory, times(1))
        .createSensorOrientationFeature(mockCameraProperties, mockActivity, mockDartMessenger);
    verify(mockCameraFeatureFactory, times(1)).createAutoFocusFeature(mockCameraProperties, false);
    verify(mockCameraFeatureFactory, times(1)).createExposureLockFeature(mockCameraProperties);
    verify(mockCameraFeatureFactory, times(1))
        .createExposurePointFeature(eq(mockCameraProperties), eq(mockSensorOrientationFeature));
    verify(mockCameraFeatureFactory, times(1)).createExposureOffsetFeature(mockCameraProperties);
    verify(mockCameraFeatureFactory, times(1)).createFlashFeature(mockCameraProperties);
    verify(mockCameraFeatureFactory, times(1))
        .createFocusPointFeature(eq(mockCameraProperties), eq(mockSensorOrientationFeature));
    verify(mockCameraFeatureFactory, times(1)).createFpsRangeFeature(mockCameraProperties);
    verify(mockCameraFeatureFactory, times(1)).createNoiseReductionFeature(mockCameraProperties);
    verify(mockCameraFeatureFactory, times(1))
        .createResolutionFeature(mockCameraProperties, resolutionPreset, cameraName);
    verify(mockCameraFeatureFactory, times(1)).createZoomLevelFeature(mockCameraProperties);
    assertNotNull("should create a camera", camera);
  }

  @Test
  public void getDeviceOrientationManager() {
    SensorOrientationFeature mockSensorOrientationFeature =
        mockCameraFeatureFactory.createSensorOrientationFeature(mockCameraProperties, null, null);
    DeviceOrientationManager mockDeviceOrientationManager = mock(DeviceOrientationManager.class);

    when(mockSensorOrientationFeature.getDeviceOrientationManager())
        .thenReturn(mockDeviceOrientationManager);

    DeviceOrientationManager actualDeviceOrientationManager = camera.getDeviceOrientationManager();

    verify(mockSensorOrientationFeature, times(1)).getDeviceOrientationManager();
    assertEquals(mockDeviceOrientationManager, actualDeviceOrientationManager);
  }

  @Test
  public void getExposureOffsetStepSize() {
    ExposureOffsetFeature mockExposureOffsetFeature =
        mockCameraFeatureFactory.createExposureOffsetFeature(mockCameraProperties);
    double stepSize = 2.3;

    when(mockExposureOffsetFeature.getExposureOffsetStepSize()).thenReturn(stepSize);

    double actualSize = camera.getExposureOffsetStepSize();

    verify(mockExposureOffsetFeature, times(1)).getExposureOffsetStepSize();
    assertEquals(stepSize, actualSize, 0);
  }

  @Test
  public void getMaxExposureOffset() {
    ExposureOffsetFeature mockExposureOffsetFeature =
        mockCameraFeatureFactory.createExposureOffsetFeature(mockCameraProperties);
    double expectedMaxOffset = 42.0;

    when(mockExposureOffsetFeature.getMaxExposureOffset()).thenReturn(expectedMaxOffset);

    double actualMaxOffset = camera.getMaxExposureOffset();

    verify(mockExposureOffsetFeature, times(1)).getMaxExposureOffset();
    assertEquals(expectedMaxOffset, actualMaxOffset, 0);
  }

  @Test
  public void getMinExposureOffset() {
    ExposureOffsetFeature mockExposureOffsetFeature =
        mockCameraFeatureFactory.createExposureOffsetFeature(mockCameraProperties);
    double expectedMinOffset = 21.5;

    when(mockExposureOffsetFeature.getMinExposureOffset()).thenReturn(21.5);

    double actualMinOffset = camera.getMinExposureOffset();

    verify(mockExposureOffsetFeature, times(1)).getMinExposureOffset();
    assertEquals(expectedMinOffset, actualMinOffset, 0);
  }

  @Test
  public void getMaxZoomLevel() {
    ZoomLevelFeature mockZoomLevelFeature =
        mockCameraFeatureFactory.createZoomLevelFeature(mockCameraProperties);
    float expectedMaxZoomLevel = 4.2f;

    when(mockZoomLevelFeature.getMaximumZoomLevel()).thenReturn(expectedMaxZoomLevel);

    float actualMaxZoomLevel = camera.getMaxZoomLevel();

    verify(mockZoomLevelFeature, times(1)).getMaximumZoomLevel();
    assertEquals(expectedMaxZoomLevel, actualMaxZoomLevel, 0);
  }

  @Test
  public void getMinZoomLevel() {
    ZoomLevelFeature mockZoomLevelFeature =
        mockCameraFeatureFactory.createZoomLevelFeature(mockCameraProperties);
    float expectedMinZoomLevel = 4.2f;

    when(mockZoomLevelFeature.getMinimumZoomLevel()).thenReturn(expectedMinZoomLevel);

    float actualMinZoomLevel = camera.getMinZoomLevel();

    verify(mockZoomLevelFeature, times(1)).getMinimumZoomLevel();
    assertEquals(expectedMinZoomLevel, actualMinZoomLevel, 0);
  }

  @Test
  public void getRecordingProfile() {
    ResolutionFeature mockResolutionFeature =
        mockCameraFeatureFactory.createResolutionFeature(mockCameraProperties, null, null);
    CamcorderProfile mockCamcorderProfile = mock(CamcorderProfile.class);

    when(mockResolutionFeature.getRecordingProfile()).thenReturn(mockCamcorderProfile);

    CamcorderProfile actualRecordingProfile = camera.getRecordingProfile();

    verify(mockResolutionFeature, times(1)).getRecordingProfile();
    assertEquals(mockCamcorderProfile, actualRecordingProfile);
  }

  @Test
  public void setExposureMode_shouldUpdateExposureLockFeature() {
    ExposureLockFeature mockExposureLockFeature =
        mockCameraFeatureFactory.createExposureLockFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    ExposureMode exposureMode = ExposureMode.locked;

    camera.setExposureMode(mockResult, exposureMode);

    verify(mockExposureLockFeature, times(1)).setValue(exposureMode);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setExposureMode_shouldUpdateBuilder() {
    ExposureLockFeature mockExposureLockFeature =
        mockCameraFeatureFactory.createExposureLockFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    ExposureMode exposureMode = ExposureMode.locked;

    camera.setExposureMode(mockResult, exposureMode);

    verify(mockExposureLockFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setExposureMode_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    ExposureMode exposureMode = ExposureMode.locked;
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setExposureMode(mockResult, exposureMode);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1))
        .error("setExposureModeFailed", "Could not set exposure mode.", null);
  }

  @Test
  public void setExposurePoint_shouldUpdateExposurePointFeature() {
    SensorOrientationFeature mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
    ExposurePointFeature mockExposurePointFeature =
        mockCameraFeatureFactory.createExposurePointFeature(
            mockCameraProperties, mockSensorOrientationFeature);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);

    camera.setExposurePoint(mockResult, point);

    verify(mockExposurePointFeature, times(1)).setValue(point);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setExposurePoint_shouldUpdateBuilder() {
    SensorOrientationFeature mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
    ExposurePointFeature mockExposurePointFeature =
        mockCameraFeatureFactory.createExposurePointFeature(
            mockCameraProperties, mockSensorOrientationFeature);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);

    camera.setExposurePoint(mockResult, point);

    verify(mockExposurePointFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setExposurePoint_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setExposurePoint(mockResult, point);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1))
        .error("setExposurePointFailed", "Could not set exposure point.", null);
  }

  @Test
  public void setFlashMode_shouldUpdateFlashFeature() {
    FlashFeature mockFlashFeature =
        mockCameraFeatureFactory.createFlashFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    FlashMode flashMode = FlashMode.always;

    camera.setFlashMode(mockResult, flashMode);

    verify(mockFlashFeature, times(1)).setValue(flashMode);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setFlashMode_shouldUpdateBuilder() {
    FlashFeature mockFlashFeature =
        mockCameraFeatureFactory.createFlashFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    FlashMode flashMode = FlashMode.always;

    camera.setFlashMode(mockResult, flashMode);

    verify(mockFlashFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setFlashMode_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    FlashMode flashMode = FlashMode.always;
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setFlashMode(mockResult, flashMode);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1)).error("setFlashModeFailed", "Could not set flash mode.", null);
  }

  @Test
  public void setFocusPoint_shouldUpdateFocusPointFeature() {
    SensorOrientationFeature mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
    FocusPointFeature mockFocusPointFeature =
        mockCameraFeatureFactory.createFocusPointFeature(
            mockCameraProperties, mockSensorOrientationFeature);
    AutoFocusFeature mockAutoFocusFeature =
        mockCameraFeatureFactory.createAutoFocusFeature(mockCameraProperties, false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);
    when(mockAutoFocusFeature.getValue()).thenReturn(FocusMode.auto);

    camera.setFocusPoint(mockResult, point);

    verify(mockFocusPointFeature, times(1)).setValue(point);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setFocusPoint_shouldUpdateBuilder() {
    SensorOrientationFeature mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
    FocusPointFeature mockFocusPointFeature =
        mockCameraFeatureFactory.createFocusPointFeature(
            mockCameraProperties, mockSensorOrientationFeature);
    AutoFocusFeature mockAutoFocusFeature =
        mockCameraFeatureFactory.createAutoFocusFeature(mockCameraProperties, false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);
    when(mockAutoFocusFeature.getValue()).thenReturn(FocusMode.auto);

    camera.setFocusPoint(mockResult, point);

    verify(mockFocusPointFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setFocusPoint_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    AutoFocusFeature mockAutoFocusFeature =
        mockCameraFeatureFactory.createAutoFocusFeature(mockCameraProperties, false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    Point point = new Point(42d, 42d);
    when(mockAutoFocusFeature.getValue()).thenReturn(FocusMode.auto);
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setFocusPoint(mockResult, point);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1)).error("setFocusPointFailed", "Could not set focus point.", null);
  }

  @Test
  public void setZoomLevel_shouldUpdateZoomLevelFeature() throws CameraAccessException {
    ZoomLevelFeature mockZoomLevelFeature =
        mockCameraFeatureFactory.createZoomLevelFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    float zoomLevel = 1.0f;

    when(mockZoomLevelFeature.getValue()).thenReturn(zoomLevel);
    when(mockZoomLevelFeature.getMinimumZoomLevel()).thenReturn(0f);
    when(mockZoomLevelFeature.getMaximumZoomLevel()).thenReturn(2f);

    camera.setZoomLevel(mockResult, zoomLevel);

    verify(mockZoomLevelFeature, times(1)).setValue(zoomLevel);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setZoomLevel_shouldUpdateBuilder() throws CameraAccessException {
    ZoomLevelFeature mockZoomLevelFeature =
        mockCameraFeatureFactory.createZoomLevelFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    float zoomLevel = 1.0f;

    when(mockZoomLevelFeature.getValue()).thenReturn(zoomLevel);
    when(mockZoomLevelFeature.getMinimumZoomLevel()).thenReturn(0f);
    when(mockZoomLevelFeature.getMaximumZoomLevel()).thenReturn(2f);

    camera.setZoomLevel(mockResult, zoomLevel);

    verify(mockZoomLevelFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setZoomLevel_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    ZoomLevelFeature mockZoomLevelFeature =
        mockCameraFeatureFactory.createZoomLevelFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    float zoomLevel = 1.0f;

    when(mockZoomLevelFeature.getValue()).thenReturn(zoomLevel);
    when(mockZoomLevelFeature.getMinimumZoomLevel()).thenReturn(0f);
    when(mockZoomLevelFeature.getMaximumZoomLevel()).thenReturn(2f);
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setZoomLevel(mockResult, zoomLevel);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1)).error("setZoomLevelFailed", "Could not set zoom level.", null);
  }

  @Test
  public void pauseVideoRecording_shouldSendNullResultWhenNotRecording() {
    TestUtils.setPrivateField(camera, "recordingVideo", false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.pauseVideoRecording(mockResult);

    verify(mockResult, times(1)).success(null);
    verify(mockResult, never()).error(any(), any(), any());
  }

  @Test
  public void pauseVideoRecording_shouldCallPauseWhenRecordingAndOnAPIN() {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    MediaRecorder mockMediaRecorder = mock(MediaRecorder.class);
    TestUtils.setPrivateField(camera, "mediaRecorder", mockMediaRecorder);
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 24);

    camera.pauseVideoRecording(mockResult);

    verify(mockMediaRecorder, times(1)).pause();
    verify(mockResult, times(1)).success(null);
    verify(mockResult, never()).error(any(), any(), any());
  }

  @Test
  public void pauseVideoRecording_shouldSendVideoRecordingFailedErrorWhenVersionCodeSmallerThenN() {
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 23);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.pauseVideoRecording(mockResult);

    verify(mockResult, times(1))
        .error("videoRecordingFailed", "pauseVideoRecording requires Android API +24.", null);
    verify(mockResult, never()).success(any());
  }

  @Test
  public void
      pauseVideoRecording_shouldSendVideoRecordingFailedErrorWhenMediaRecorderPauseThrowsIllegalStateException() {
    MediaRecorder mockMediaRecorder = mock(MediaRecorder.class);
    TestUtils.setPrivateField(camera, "mediaRecorder", mockMediaRecorder);
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 24);

    IllegalStateException expectedException = new IllegalStateException("Test error message");

    doThrow(expectedException).when(mockMediaRecorder).pause();

    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.pauseVideoRecording(mockResult);

    verify(mockResult, times(1)).error("videoRecordingFailed", "Test error message", null);
    verify(mockResult, never()).success(any());
  }

  @Test
  public void resumeVideoRecording_shouldSendNullResultWhenNotRecording() {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    TestUtils.setPrivateField(camera, "recordingVideo", false);

    camera.resumeVideoRecording(mockResult);

    verify(mockResult, times(1)).success(null);
    verify(mockResult, never()).error(any(), any(), any());
  }

  @Test
  public void resumeVideoRecording_shouldCallPauseWhenRecordingAndOnAPIN() {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    MediaRecorder mockMediaRecorder = mock(MediaRecorder.class);
    TestUtils.setPrivateField(camera, "mediaRecorder", mockMediaRecorder);
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 24);

    camera.resumeVideoRecording(mockResult);

    verify(mockMediaRecorder, times(1)).resume();
    verify(mockResult, times(1)).success(null);
    verify(mockResult, never()).error(any(), any(), any());
  }

  @Test
  public void
      resumeVideoRecording_shouldSendVideoRecordingFailedErrorWhenVersionCodeSmallerThanN() {
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 23);

    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.resumeVideoRecording(mockResult);

    verify(mockResult, times(1))
        .error("videoRecordingFailed", "resumeVideoRecording requires Android API +24.", null);
    verify(mockResult, never()).success(any());
  }

  @Test
  public void
      resumeVideoRecording_shouldSendVideoRecordingFailedErrorWhenMediaRecorderPauseThrowsIllegalStateException() {
    MediaRecorder mockMediaRecorder = mock(MediaRecorder.class);
    TestUtils.setPrivateField(camera, "mediaRecorder", mockMediaRecorder);
    TestUtils.setPrivateField(camera, "recordingVideo", true);
    TestUtils.setFinalStatic(Build.VERSION.class, "SDK_INT", 24);

    IllegalStateException expectedException = new IllegalStateException("Test error message");

    doThrow(expectedException).when(mockMediaRecorder).resume();

    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.resumeVideoRecording(mockResult);

    verify(mockResult, times(1)).error("videoRecordingFailed", "Test error message", null);
    verify(mockResult, never()).success(any());
  }

  @Test
  public void setFocusMode_shouldUpdateAutoFocusFeature() {
    AutoFocusFeature mockAutoFocusFeature =
        mockCameraFeatureFactory.createAutoFocusFeature(mockCameraProperties, false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.setFocusMode(mockResult, FocusMode.auto);

    verify(mockAutoFocusFeature, times(1)).setValue(FocusMode.auto);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(null);
  }

  @Test
  public void setFocusMode_shouldUpdateBuilder() {
    AutoFocusFeature mockAutoFocusFeature =
        mockCameraFeatureFactory.createAutoFocusFeature(mockCameraProperties, false);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.setFocusMode(mockResult, FocusMode.auto);

    verify(mockAutoFocusFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setFocusMode_shouldUnlockAutoFocusForAutoMode() {
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.auto);
    verify(mockPreviewRequestBuilder, times(1))
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
    verify(mockPreviewRequestBuilder, times(1))
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
  }

  @Test
  public void setFocusMode_shouldSkipUnlockAutoFocusWhenNullCaptureSession() {
    TestUtils.setPrivateField(camera, "captureSession", null);
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.auto);
    verify(mockPreviewRequestBuilder, never())
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
    verify(mockPreviewRequestBuilder, never())
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
  }

  @Test
  public void setFocusMode_shouldSendErrorEventOnUnlockAutoFocusCameraAccessException()
      throws CameraAccessException {
    when(mockCaptureSession.capture(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.auto);
    verify(mockDartMessenger, times(1)).sendCameraErrorEvent(any());
  }

  @Test
  public void setFocusMode_shouldLockAutoFocusForLockedMode() throws CameraAccessException {
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.locked);
    verify(mockPreviewRequestBuilder, times(1))
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START);
    verify(mockCaptureSession, times(1)).capture(any(), any(), any());
    verify(mockCaptureSession, times(1)).setRepeatingRequest(any(), any(), any());
  }

  @Test
  public void setFocusMode_shouldSkipLockAutoFocusWhenNullCaptureSession() {
    TestUtils.setPrivateField(camera, "captureSession", null);
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.locked);
    verify(mockPreviewRequestBuilder, never())
        .set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
  }

  @Test
  public void setFocusMode_shouldSendErrorEventOnLockAutoFocusCameraAccessException()
      throws CameraAccessException {
    when(mockCaptureSession.capture(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));
    camera.setFocusMode(mock(MethodChannel.Result.class), FocusMode.locked);
    verify(mockDartMessenger, times(1)).sendCameraErrorEvent(any());
  }

  @Test
  public void setFocusMode_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setFocusMode(mockResult, FocusMode.locked);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1))
        .error("setFocusModeFailed", "Error setting focus mode: null", null);
  }

  @Test
  public void setExposureOffset_shouldUpdateExposureOffsetFeature() {
    ExposureOffsetFeature mockExposureOffsetFeature =
        mockCameraFeatureFactory.createExposureOffsetFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    when(mockExposureOffsetFeature.getValue()).thenReturn(1.0);

    camera.setExposureOffset(mockResult, 1.0);

    verify(mockExposureOffsetFeature, times(1)).setValue(1.0);
    verify(mockResult, never()).error(any(), any(), any());
    verify(mockResult, times(1)).success(1.0);
  }

  @Test
  public void setExposureOffset_shouldAndUpdateBuilder() {
    ExposureOffsetFeature mockExposureOffsetFeature =
        mockCameraFeatureFactory.createExposureOffsetFeature(mockCameraProperties);
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);

    camera.setExposureOffset(mockResult, 1.0);

    verify(mockExposureOffsetFeature, times(1)).updateBuilder(any());
  }

  @Test
  public void setExposureOffset_shouldCallErrorOnResultOnCameraAccessException()
      throws CameraAccessException {
    MethodChannel.Result mockResult = mock(MethodChannel.Result.class);
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0, ""));

    camera.setExposureOffset(mockResult, 1.0);

    verify(mockResult, never()).success(any());
    verify(mockResult, times(1))
        .error("setExposureOffsetFailed", "Could not set exposure offset.", null);
  }

  @Test
  public void lockCaptureOrientation_shouldLockCaptureOrientation() {
    final Activity mockActivity = mock(Activity.class);
    SensorOrientationFeature mockSensorOrientationFeature =
        mockCameraFeatureFactory.createSensorOrientationFeature(
            mockCameraProperties, mockActivity, mockDartMessenger);

    camera.lockCaptureOrientation(PlatformChannel.DeviceOrientation.PORTRAIT_UP);

    verify(mockSensorOrientationFeature, times(1))
        .lockCaptureOrientation(PlatformChannel.DeviceOrientation.PORTRAIT_UP);
  }

  @Test
  public void unlockCaptureOrientation_shouldUnlockCaptureOrientation() {
    final Activity mockActivity = mock(Activity.class);
    SensorOrientationFeature mockSensorOrientationFeature =
        mockCameraFeatureFactory.createSensorOrientationFeature(
            mockCameraProperties, mockActivity, mockDartMessenger);

    camera.unlockCaptureOrientation();

    verify(mockSensorOrientationFeature, times(1)).unlockCaptureOrientation();
  }

  @Test
  public void pausePreview_shouldPausePreview() throws CameraAccessException {
    camera.pausePreview();

    assertEquals(TestUtils.getPrivateField(camera, "pausedPreview"), true);
    verify(mockCaptureSession, times(1)).stopRepeating();
  }

  @Test
  public void resumePreview_shouldResumePreview() throws CameraAccessException {
    camera.resumePreview();

    assertEquals(TestUtils.getPrivateField(camera, "pausedPreview"), false);
    verify(mockCaptureSession, times(1)).setRepeatingRequest(any(), any(), any());
  }

  @Test
  public void resumePreview_shouldSendErrorEventOnCameraAccessException()
      throws CameraAccessException {
    when(mockCaptureSession.setRepeatingRequest(any(), any(), any()))
        .thenThrow(new CameraAccessException(0));

    camera.resumePreview();

    verify(mockDartMessenger, times(1)).sendCameraErrorEvent(any());
  }

  private static class TestCameraFeatureFactory implements CameraFeatureFactory {
    private final AutoFocusFeature mockAutoFocusFeature;
    private final ExposureLockFeature mockExposureLockFeature;
    private final ExposureOffsetFeature mockExposureOffsetFeature;
    private final ExposurePointFeature mockExposurePointFeature;
    private final FlashFeature mockFlashFeature;
    private final FocusPointFeature mockFocusPointFeature;
    private final FpsRangeFeature mockFpsRangeFeature;
    private final NoiseReductionFeature mockNoiseReductionFeature;
    private final ResolutionFeature mockResolutionFeature;
    private final SensorOrientationFeature mockSensorOrientationFeature;
    private final ZoomLevelFeature mockZoomLevelFeature;

    public TestCameraFeatureFactory() {
      this.mockAutoFocusFeature = mock(AutoFocusFeature.class);
      this.mockExposureLockFeature = mock(ExposureLockFeature.class);
      this.mockExposureOffsetFeature = mock(ExposureOffsetFeature.class);
      this.mockExposurePointFeature = mock(ExposurePointFeature.class);
      this.mockFlashFeature = mock(FlashFeature.class);
      this.mockFocusPointFeature = mock(FocusPointFeature.class);
      this.mockFpsRangeFeature = mock(FpsRangeFeature.class);
      this.mockNoiseReductionFeature = mock(NoiseReductionFeature.class);
      this.mockResolutionFeature = mock(ResolutionFeature.class);
      this.mockSensorOrientationFeature = mock(SensorOrientationFeature.class);
      this.mockZoomLevelFeature = mock(ZoomLevelFeature.class);
    }

    @Override
    public AutoFocusFeature createAutoFocusFeature(
        @NonNull CameraProperties cameraProperties, boolean recordingVideo) {
      return mockAutoFocusFeature;
    }

    @Override
    public ExposureLockFeature createExposureLockFeature(
        @NonNull CameraProperties cameraProperties) {
      return mockExposureLockFeature;
    }

    @Override
    public ExposureOffsetFeature createExposureOffsetFeature(
        @NonNull CameraProperties cameraProperties) {
      return mockExposureOffsetFeature;
    }

    @Override
    public FlashFeature createFlashFeature(@NonNull CameraProperties cameraProperties) {
      return mockFlashFeature;
    }

    @Override
    public ResolutionFeature createResolutionFeature(
        @NonNull CameraProperties cameraProperties,
        ResolutionPreset initialSetting,
        String cameraName) {
      return mockResolutionFeature;
    }

    @Override
    public FocusPointFeature createFocusPointFeature(
        @NonNull CameraProperties cameraProperties,
        @NonNull SensorOrientationFeature sensorOrienttionFeature) {
      return mockFocusPointFeature;
    }

    @Override
    public FpsRangeFeature createFpsRangeFeature(@NonNull CameraProperties cameraProperties) {
      return mockFpsRangeFeature;
    }

    @Override
    public SensorOrientationFeature createSensorOrientationFeature(
        @NonNull CameraProperties cameraProperties,
        @NonNull Activity activity,
        @NonNull DartMessenger dartMessenger) {
      return mockSensorOrientationFeature;
    }

    @Override
    public ZoomLevelFeature createZoomLevelFeature(@NonNull CameraProperties cameraProperties) {
      return mockZoomLevelFeature;
    }

    @Override
    public ExposurePointFeature createExposurePointFeature(
        @NonNull CameraProperties cameraProperties,
        @NonNull SensorOrientationFeature sensorOrientationFeature) {
      return mockExposurePointFeature;
    }

    @Override
    public NoiseReductionFeature createNoiseReductionFeature(
        @NonNull CameraProperties cameraProperties) {
      return mockNoiseReductionFeature;
    }
  }
}
