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

// ignore: implementation_imports
import 'dart:js_interop';

import 'package:camera_web/src/types/types.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('CameraOptions', () {
    testWidgets('serializes correctly', (WidgetTester tester) async {
      final CameraOptions cameraOptions = CameraOptions(
        audio: const AudioConstraints(enabled: true),
        video: VideoConstraints(
          facingMode: FacingModeConstraint.exact(CameraType.user),
        ),
      );

      expect(
        cameraOptions.toMediaStreamConstraints().dartify(),
        equals(<String, Object>{
          'audio': cameraOptions.audio.toMediaStreamConstraints().dartify()!,
          'video': cameraOptions.video.toMediaStreamConstraints().dartify()!,
        }),
      );
    });

    testWidgets('supports value equality', (WidgetTester tester) async {
      expect(
        CameraOptions(
          audio: const AudioConstraints(),
          video: VideoConstraints(
            facingMode: FacingModeConstraint(CameraType.environment),
            width:
                const VideoSizeConstraint(minimum: 10, ideal: 15, maximum: 20),
            height:
                const VideoSizeConstraint(minimum: 15, ideal: 20, maximum: 25),
            deviceId: 'deviceId',
          ),
        ),
        equals(
          CameraOptions(
            audio: const AudioConstraints(),
            video: VideoConstraints(
              facingMode: FacingModeConstraint(CameraType.environment),
              width: const VideoSizeConstraint(
                  minimum: 10, ideal: 15, maximum: 20),
              height: const VideoSizeConstraint(
                  minimum: 15, ideal: 20, maximum: 25),
              deviceId: 'deviceId',
            ),
          ),
        ),
      );
    });
  });

  group('AudioConstraints', () {
    testWidgets('serializes correctly', (WidgetTester tester) async {
      expect(
        const AudioConstraints(enabled: true).toMediaStreamConstraints(),
        true.toJS,
      );
    });

    testWidgets('supports value equality', (WidgetTester tester) async {
      expect(
        const AudioConstraints(enabled: true),
        equals(const AudioConstraints(enabled: true)),
      );
    });
  });

  group('VideoConstraints', () {
    testWidgets('serializes correctly', (WidgetTester tester) async {
      final VideoConstraints videoConstraints = VideoConstraints(
        facingMode: FacingModeConstraint.exact(CameraType.user),
        width: const VideoSizeConstraint(ideal: 100, maximum: 100),
        height: const VideoSizeConstraint(ideal: 50, maximum: 50),
        deviceId: 'deviceId',
      );

      expect(
        videoConstraints.toMediaStreamConstraints().dartify(),
        equals(<String, Object>{
          'facingMode': videoConstraints.facingMode!.toJson(),
          'width': videoConstraints.width!.toJson(),
          'height': videoConstraints.height!.toJson(),
          'deviceId': <String, Object>{
            'exact': 'deviceId',
          }
        }),
      );
    });

    testWidgets('supports value equality', (WidgetTester tester) async {
      expect(
        VideoConstraints(
          facingMode: FacingModeConstraint.exact(CameraType.environment),
          width:
              const VideoSizeConstraint(minimum: 90, ideal: 100, maximum: 100),
          height:
              const VideoSizeConstraint(minimum: 40, ideal: 50, maximum: 50),
          deviceId: 'deviceId',
        ),
        equals(
          VideoConstraints(
            facingMode: FacingModeConstraint.exact(CameraType.environment),
            width: const VideoSizeConstraint(
                minimum: 90, ideal: 100, maximum: 100),
            height:
                const VideoSizeConstraint(minimum: 40, ideal: 50, maximum: 50),
            deviceId: 'deviceId',
          ),
        ),
      );
    });
  });

  group('FacingModeConstraint', () {
    group('ideal', () {
      testWidgets(
          'serializes correctly '
          'for environment camera type', (WidgetTester tester) async {
        expect(
          FacingModeConstraint(CameraType.environment).toJson(),
          equals(<String, Object>{'ideal': 'environment'}),
        );
      });

      testWidgets(
          'serializes correctly '
          'for user camera type', (WidgetTester tester) async {
        expect(
          FacingModeConstraint(CameraType.user).toJson(),
          equals(<String, Object>{'ideal': 'user'}),
        );
      });

      testWidgets('supports value equality', (WidgetTester tester) async {
        expect(
          FacingModeConstraint(CameraType.user),
          equals(FacingModeConstraint(CameraType.user)),
        );
      });
    });

    group('exact', () {
      testWidgets(
          'serializes correctly '
          'for environment camera type', (WidgetTester tester) async {
        expect(
          FacingModeConstraint.exact(CameraType.environment).toJson(),
          equals(<String, Object>{'exact': 'environment'}),
        );
      });

      testWidgets(
          'serializes correctly '
          'for user camera type', (WidgetTester tester) async {
        expect(
          FacingModeConstraint.exact(CameraType.user).toJson(),
          equals(<String, Object>{'exact': 'user'}),
        );
      });

      testWidgets('supports value equality', (WidgetTester tester) async {
        expect(
          FacingModeConstraint.exact(CameraType.environment),
          equals(FacingModeConstraint.exact(CameraType.environment)),
        );
      });
    });
  });

  group('VideoSizeConstraint ', () {
    testWidgets('serializes correctly', (WidgetTester tester) async {
      expect(
        const VideoSizeConstraint(
          minimum: 200,
          ideal: 400,
          maximum: 400,
        ).toJson(),
        equals(<String, Object>{
          'min': 200,
          'ideal': 400,
          'max': 400,
        }),
      );
    });

    testWidgets('supports value equality', (WidgetTester tester) async {
      expect(
        const VideoSizeConstraint(
          minimum: 100,
          ideal: 200,
          maximum: 300,
        ),
        equals(
          const VideoSizeConstraint(
            minimum: 100,
            ideal: 200,
            maximum: 300,
          ),
        ),
      );
    });
  });
}
