// 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.

import 'package:async/async.dart';
import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_windows/camera_windows.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_test/flutter_test.dart';
import './utils/method_channel_mock.dart';

void main() {
  const String pluginChannelName = 'plugins.flutter.io/camera_windows';
  TestWidgetsFlutterBinding.ensureInitialized();

  group('$CameraWindows()', () {
    test('registered instance', () {
      CameraWindows.registerWith();
      expect(CameraPlatform.instance, isA<CameraWindows>());
    });

    group('Creation, Initialization & Disposal Tests', () {
      test('Should send creation data and receive back a camera id', () async {
        // Arrange
        final MethodChannelMock cameraMockChannel = MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'create': <String, dynamic>{
                'cameraId': 1,
                'imageFormatGroup': 'unknown',
              }
            });
        final CameraWindows plugin = CameraWindows();

        // Act
        final int cameraId = await plugin.createCamera(
          const CameraDescription(
              name: 'Test',
              lensDirection: CameraLensDirection.front,
              sensorOrientation: 0),
          ResolutionPreset.high,
        );

        // Assert
        expect(cameraMockChannel.log, <Matcher>[
          isMethodCall(
            'create',
            arguments: <String, Object?>{
              'cameraName': 'Test',
              'resolutionPreset': 'high',
              'enableAudio': false
            },
          ),
        ]);
        expect(cameraId, 1);
      });

      test(
          'Should throw CameraException when create throws a PlatformException',
          () {
        // Arrange
        MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'create': PlatformException(
                code: 'TESTING_ERROR_CODE',
                message: 'Mock error message used during testing.',
              )
            });
        final CameraWindows plugin = CameraWindows();

        // Act
        expect(
          () => plugin.createCamera(
            const CameraDescription(
              name: 'Test',
              lensDirection: CameraLensDirection.back,
              sensorOrientation: 0,
            ),
            ResolutionPreset.high,
          ),
          throwsA(
            isA<CameraException>()
                .having(
                    (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE')
                .having((CameraException e) => e.description, 'description',
                    'Mock error message used during testing.'),
          ),
        );
      });

      test(
        'Should throw CameraException when initialize throws a PlatformException',
        () {
          // Arrange
          MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'initialize': PlatformException(
                code: 'TESTING_ERROR_CODE',
                message: 'Mock error message used during testing.',
              )
            },
          );
          final CameraWindows plugin = CameraWindows();

          // Act
          expect(
            () => plugin.initializeCamera(0),
            throwsA(
              isA<CameraException>()
                  .having((CameraException e) => e.code, 'code',
                      'TESTING_ERROR_CODE')
                  .having(
                    (CameraException e) => e.description,
                    'description',
                    'Mock error message used during testing.',
                  ),
            ),
          );
        },
      );

      test('Should send initialization data', () async {
        // Arrange
        final MethodChannelMock cameraMockChannel = MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'create': <String, dynamic>{
                'cameraId': 1,
                'imageFormatGroup': 'unknown',
              },
              'initialize': <String, dynamic>{
                'previewWidth': 1920.toDouble(),
                'previewHeight': 1080.toDouble()
              },
            });
        final CameraWindows plugin = CameraWindows();
        final int cameraId = await plugin.createCamera(
          const CameraDescription(
            name: 'Test',
            lensDirection: CameraLensDirection.back,
            sensorOrientation: 0,
          ),
          ResolutionPreset.high,
        );

        // Act
        await plugin.initializeCamera(cameraId);

        // Assert
        expect(cameraId, 1);
        expect(cameraMockChannel.log, <Matcher>[
          anything,
          isMethodCall(
            'initialize',
            arguments: <String, Object?>{'cameraId': 1},
          ),
        ]);
      });

      test('Should send a disposal call on dispose', () async {
        // Arrange
        final MethodChannelMock cameraMockChannel = MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'create': <String, dynamic>{'cameraId': 1},
              'initialize': <String, dynamic>{
                'previewWidth': 1920.toDouble(),
                'previewHeight': 1080.toDouble()
              },
              'dispose': <String, dynamic>{'cameraId': 1}
            });

        final CameraWindows plugin = CameraWindows();
        final int cameraId = await plugin.createCamera(
          const CameraDescription(
            name: 'Test',
            lensDirection: CameraLensDirection.back,
            sensorOrientation: 0,
          ),
          ResolutionPreset.high,
        );
        await plugin.initializeCamera(cameraId);

        // Act
        await plugin.dispose(cameraId);

        // Assert
        expect(cameraId, 1);
        expect(cameraMockChannel.log, <Matcher>[
          anything,
          anything,
          isMethodCall(
            'dispose',
            arguments: <String, Object?>{'cameraId': 1},
          ),
        ]);
      });
    });

    group('Event Tests', () {
      late CameraWindows plugin;
      late int cameraId;
      setUp(() async {
        MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{
            'create': <String, dynamic>{'cameraId': 1},
            'initialize': <String, dynamic>{
              'previewWidth': 1920.toDouble(),
              'previewHeight': 1080.toDouble()
            },
          },
        );

        plugin = CameraWindows();
        cameraId = await plugin.createCamera(
          const CameraDescription(
            name: 'Test',
            lensDirection: CameraLensDirection.back,
            sensorOrientation: 0,
          ),
          ResolutionPreset.high,
        );
        await plugin.initializeCamera(cameraId);
      });

      test('Should receive camera closing events', () async {
        // Act
        final Stream<CameraClosingEvent> eventStream =
            plugin.onCameraClosing(cameraId);
        final StreamQueue<CameraClosingEvent> streamQueue =
            StreamQueue<CameraClosingEvent>(eventStream);

        // Emit test events
        final CameraClosingEvent event = CameraClosingEvent(cameraId);
        await plugin.handleCameraMethodCall(
            MethodCall('camera_closing', event.toJson()), cameraId);
        await plugin.handleCameraMethodCall(
            MethodCall('camera_closing', event.toJson()), cameraId);
        await plugin.handleCameraMethodCall(
            MethodCall('camera_closing', event.toJson()), cameraId);

        // Assert
        expect(await streamQueue.next, event);
        expect(await streamQueue.next, event);
        expect(await streamQueue.next, event);

        // Clean up
        await streamQueue.cancel();
      });

      test('Should receive camera error events', () async {
        // Act
        final Stream<CameraErrorEvent> errorStream =
            plugin.onCameraError(cameraId);
        final StreamQueue<CameraErrorEvent> streamQueue =
            StreamQueue<CameraErrorEvent>(errorStream);

        // Emit test events
        final CameraErrorEvent event =
            CameraErrorEvent(cameraId, 'Error Description');
        await plugin.handleCameraMethodCall(
            MethodCall('error', event.toJson()), cameraId);
        await plugin.handleCameraMethodCall(
            MethodCall('error', event.toJson()), cameraId);
        await plugin.handleCameraMethodCall(
            MethodCall('error', event.toJson()), cameraId);

        // Assert
        expect(await streamQueue.next, event);
        expect(await streamQueue.next, event);
        expect(await streamQueue.next, event);

        // Clean up
        await streamQueue.cancel();
      });
    });

    group('Function Tests', () {
      late CameraWindows plugin;
      late int cameraId;

      setUp(() async {
        MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{
            'create': <String, dynamic>{'cameraId': 1},
            'initialize': <String, dynamic>{
              'previewWidth': 1920.toDouble(),
              'previewHeight': 1080.toDouble()
            },
          },
        );
        plugin = CameraWindows();
        cameraId = await plugin.createCamera(
          const CameraDescription(
            name: 'Test',
            lensDirection: CameraLensDirection.back,
            sensorOrientation: 0,
          ),
          ResolutionPreset.high,
        );
        await plugin.initializeCamera(cameraId);
      });

      test('Should fetch CameraDescription instances for available cameras',
          () async {
        // Arrange
        final List<dynamic> returnData = <dynamic>[
          <String, dynamic>{
            'name': 'Test 1',
            'lensFacing': 'front',
            'sensorOrientation': 1
          },
          <String, dynamic>{
            'name': 'Test 2',
            'lensFacing': 'back',
            'sensorOrientation': 2
          }
        ];
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'availableCameras': returnData},
        );

        // Act
        final List<CameraDescription> cameras = await plugin.availableCameras();

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('availableCameras', arguments: null),
        ]);
        expect(cameras.length, returnData.length);
        for (int i = 0; i < returnData.length; i++) {
          final Map<String, Object?> typedData =
              (returnData[i] as Map<dynamic, dynamic>).cast<String, Object?>();
          final CameraDescription cameraDescription = CameraDescription(
            name: typedData['name']! as String,
            lensDirection: plugin
                .parseCameraLensDirection(typedData['lensFacing']! as String),
            sensorOrientation: typedData['sensorOrientation']! as int,
          );
          expect(cameras[i], cameraDescription);
        }
      });

      test(
          'Should throw CameraException when availableCameras throws a PlatformException',
          () {
        // Arrange
        MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{
              'availableCameras': PlatformException(
                code: 'TESTING_ERROR_CODE',
                message: 'Mock error message used during testing.',
              )
            });

        // Act
        expect(
          plugin.availableCameras,
          throwsA(
            isA<CameraException>()
                .having(
                    (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE')
                .having((CameraException e) => e.description, 'description',
                    'Mock error message used during testing.'),
          ),
        );
      });

      test('Should take a picture and return an XFile instance', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
            channelName: pluginChannelName,
            methods: <String, dynamic>{'takePicture': '/test/path.jpg'});

        // Act
        final XFile file = await plugin.takePicture(cameraId);

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('takePicture', arguments: <String, Object?>{
            'cameraId': cameraId,
          }),
        ]);
        expect(file.path, '/test/path.jpg');
      });

      test('Should prepare for video recording', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'prepareForVideoRecording': null},
        );

        // Act
        await plugin.prepareForVideoRecording();

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('prepareForVideoRecording', arguments: null),
        ]);
      });

      test('Should start recording a video', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'startVideoRecording': null},
        );

        // Act
        await plugin.startVideoRecording(cameraId);

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('startVideoRecording', arguments: <String, Object?>{
            'cameraId': cameraId,
            'maxVideoDuration': null,
          }),
        ]);
      });

      test('Should pass maxVideoDuration when starting recording a video',
          () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'startVideoRecording': null},
        );

        // Act
        await plugin.startVideoRecording(
          cameraId,
          maxVideoDuration: const Duration(seconds: 10),
        );

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('startVideoRecording', arguments: <String, Object?>{
            'cameraId': cameraId,
            'maxVideoDuration': 10000
          }),
        ]);
      });

      test('capturing fails if trying to stream', () async {
        // Act and Assert
        expect(
          () => plugin.startVideoCapturing(VideoCaptureOptions(cameraId,
              streamCallback: (CameraImageData imageData) {})),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should stop a video recording and return the file', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'stopVideoRecording': '/test/path.mp4'},
        );

        // Act
        final XFile file = await plugin.stopVideoRecording(cameraId);

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('stopVideoRecording', arguments: <String, Object?>{
            'cameraId': cameraId,
          }),
        ]);
        expect(file.path, '/test/path.mp4');
      });

      test('Should throw UnsupportedError when pause video recording is called',
          () async {
        // Act
        expect(
          () => plugin.pauseVideoRecording(cameraId),
          throwsA(isA<UnsupportedError>()),
        );
      });

      test(
          'Should throw UnsupportedError when resume video recording is called',
          () async {
        // Act
        expect(
          () => plugin.resumeVideoRecording(cameraId),
          throwsA(isA<UnsupportedError>()),
        );
      });

      test('Should throw UnimplementedError when flash mode is set', () async {
        // Act
        expect(
          () => plugin.setFlashMode(cameraId, FlashMode.torch),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should throw UnimplementedError when exposure mode is set',
          () async {
        // Act
        expect(
          () => plugin.setExposureMode(cameraId, ExposureMode.auto),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should throw UnsupportedError when exposure point is set',
          () async {
        // Act
        expect(
          () => plugin.setExposurePoint(cameraId, null),
          throwsA(isA<UnsupportedError>()),
        );
      });

      test('Should get the min exposure offset', () async {
        // Act
        final double minExposureOffset =
            await plugin.getMinExposureOffset(cameraId);

        // Assert
        expect(minExposureOffset, 0.0);
      });

      test('Should get the max exposure offset', () async {
        // Act
        final double maxExposureOffset =
            await plugin.getMaxExposureOffset(cameraId);

        // Assert
        expect(maxExposureOffset, 0.0);
      });

      test('Should get the exposure offset step size', () async {
        // Act
        final double stepSize =
            await plugin.getExposureOffsetStepSize(cameraId);

        // Assert
        expect(stepSize, 1.0);
      });

      test('Should throw UnimplementedError when exposure offset is set',
          () async {
        // Act
        expect(
          () => plugin.setExposureOffset(cameraId, 0.5),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should throw UnimplementedError when focus mode is set', () async {
        // Act
        expect(
          () => plugin.setFocusMode(cameraId, FocusMode.auto),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should throw UnsupportedError when exposure point is set',
          () async {
        // Act
        expect(
          () => plugin.setFocusMode(cameraId, FocusMode.auto),
          throwsA(isA<UnsupportedError>()),
        );
      });

      test('Should build a texture widget as preview widget', () async {
        // Act
        final Widget widget = plugin.buildPreview(cameraId);

        // Act
        expect(widget is Texture, isTrue);
        expect((widget as Texture).textureId, cameraId);
      });

      test('Should throw UnimplementedError when handling unknown method', () {
        final CameraWindows plugin = CameraWindows();

        expect(
            () => plugin.handleCameraMethodCall(
                const MethodCall('unknown_method'), 1),
            throwsA(isA<UnimplementedError>()));
      });

      test('Should get the max zoom level', () async {
        // Act
        final double maxZoomLevel = await plugin.getMaxZoomLevel(cameraId);

        // Assert
        expect(maxZoomLevel, 1.0);
      });

      test('Should get the min zoom level', () async {
        // Act
        final double maxZoomLevel = await plugin.getMinZoomLevel(cameraId);

        // Assert
        expect(maxZoomLevel, 1.0);
      });

      test('Should throw UnimplementedError when zoom level is set', () async {
        // Act
        expect(
          () => plugin.setZoomLevel(cameraId, 2.0),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test(
          'Should throw UnimplementedError when lock capture orientation is called',
          () async {
        // Act
        expect(
          () => plugin.setZoomLevel(cameraId, 2.0),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test(
          'Should throw UnimplementedError when unlock capture orientation is called',
          () async {
        // Act
        expect(
          () => plugin.unlockCaptureOrientation(cameraId),
          throwsA(isA<UnimplementedError>()),
        );
      });

      test('Should pause the camera preview', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'pausePreview': null},
        );

        // Act
        await plugin.pausePreview(cameraId);

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('pausePreview',
              arguments: <String, Object?>{'cameraId': cameraId}),
        ]);
      });

      test('Should resume the camera preview', () async {
        // Arrange
        final MethodChannelMock channel = MethodChannelMock(
          channelName: pluginChannelName,
          methods: <String, dynamic>{'resumePreview': null},
        );

        // Act
        await plugin.resumePreview(cameraId);

        // Assert
        expect(channel.log, <Matcher>[
          isMethodCall('resumePreview',
              arguments: <String, Object?>{'cameraId': cameraId}),
        ]);
      });
    });
  });
}
