// 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 'dart:async';
import 'dart:html' as html;
import 'dart:math';

import 'package:camera_platform_interface/camera_platform_interface.dart';
import 'package:camera_web/src/camera.dart';
import 'package:camera_web/src/camera_settings.dart';
import 'package:camera_web/src/types/types.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:stream_transform/stream_transform.dart';

// The default error message, when the error is an empty string.
// See: https://developer.mozilla.org/en-US/docs/Web/API/MediaError/message
const String _kDefaultErrorMessage =
    'No further diagnostic information can be determined or provided.';

/// The web implementation of [CameraPlatform].
///
/// This class implements the `package:camera` functionality for the web.
class CameraPlugin extends CameraPlatform {
  /// Creates a new instance of [CameraPlugin]
  /// with the given [cameraSettings] utility.
  CameraPlugin({required CameraSettings cameraSettings})
      : _cameraSettings = cameraSettings;

  /// Registers this class as the default instance of [CameraPlatform].
  static void registerWith(Registrar registrar) {
    CameraPlatform.instance = CameraPlugin(
      cameraSettings: CameraSettings(),
    );
  }

  final CameraSettings _cameraSettings;

  /// The cameras managed by the [CameraPlugin].
  @visibleForTesting
  final cameras = <int, Camera>{};
  var _textureCounter = 1;

  /// Metadata associated with each camera description.
  /// Populated in [availableCameras].
  @visibleForTesting
  final camerasMetadata = <CameraDescription, CameraMetadata>{};

  /// The controller used to broadcast different camera events.
  ///
  /// It is `broadcast` as multiple controllers may subscribe
  /// to different stream views of this controller.
  @visibleForTesting
  final cameraEventStreamController = StreamController<CameraEvent>.broadcast();

  final _cameraVideoErrorSubscriptions =
      <int, StreamSubscription<html.Event>>{};

  final _cameraVideoAbortSubscriptions =
      <int, StreamSubscription<html.Event>>{};

  /// Returns a stream of camera events for the given [cameraId].
  Stream<CameraEvent> _cameraEvents(int cameraId) =>
      cameraEventStreamController.stream
          .where((event) => event.cameraId == cameraId);

  /// The current browser window used to access media devices.
  @visibleForTesting
  html.Window? window = html.window;

  @override
  Future<List<CameraDescription>> availableCameras() async {
    try {
      final mediaDevices = window?.navigator.mediaDevices;
      final cameras = <CameraDescription>[];

      // Throw a not supported exception if the current browser window
      // does not support any media devices.
      if (mediaDevices == null) {
        throw PlatformException(
          code: CameraErrorCode.notSupported.toString(),
          message: 'The camera is not supported on this device.',
        );
      }

      // Request video and audio permissions.
      await _cameraSettings.getMediaStreamForOptions(
        CameraOptions(
          audio: AudioConstraints(enabled: true),
        ),
      );

      // Request available media devices.
      final devices = await mediaDevices.enumerateDevices();

      // Filter video input devices.
      final videoInputDevices = devices
          .whereType<html.MediaDeviceInfo>()
          .where((device) => device.kind == MediaDeviceKind.videoInput)

          /// The device id property is currently not supported on Internet Explorer:
          /// https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/deviceId#browser_compatibility
          .where(
            (device) => device.deviceId != null && device.deviceId!.isNotEmpty,
          );

      // Map video input devices to camera descriptions.
      for (final videoInputDevice in videoInputDevices) {
        // Get the video stream for the current video input device
        // to later use for the available video tracks.
        final videoStream = await _getVideoStreamForDevice(
          videoInputDevice.deviceId!,
        );

        // Get all video tracks in the video stream
        // to later extract the lens direction from the first track.
        final videoTracks = videoStream.getVideoTracks();

        if (videoTracks.isNotEmpty) {
          // Get the facing mode from the first available video track.
          final facingMode =
              _cameraSettings.getFacingModeForVideoTrack(videoTracks.first);

          // Get the lens direction based on the facing mode.
          // Fallback to the external lens direction
          // if the facing mode is not available.
          final lensDirection = facingMode != null
              ? _cameraSettings.mapFacingModeToLensDirection(facingMode)
              : CameraLensDirection.external;

          // Create a camera description.
          //
          // The name is a camera label which might be empty
          // if no permissions to media devices have been granted.
          //
          // MediaDeviceInfo.label:
          // https://developer.mozilla.org/en-US/docs/Web/API/MediaDeviceInfo/label
          //
          // Sensor orientation is currently not supported.
          final cameraLabel = videoInputDevice.label ?? '';
          final camera = CameraDescription(
            name: cameraLabel,
            lensDirection: lensDirection,
            sensorOrientation: 0,
          );

          final cameraMetadata = CameraMetadata(
            deviceId: videoInputDevice.deviceId!,
            facingMode: facingMode,
          );

          cameras.add(camera);

          camerasMetadata[camera] = cameraMetadata;
        } else {
          // Ignore as no video tracks exist in the current video input device.
          continue;
        }
      }

      return cameras;
    } on html.DomException catch (e) {
      throw CameraException(e.name, e.message);
    } on PlatformException catch (e) {
      throw CameraException(e.code, e.message);
    } on CameraWebException catch (e) {
      _addCameraErrorEvent(e);
      throw CameraException(e.code.toString(), e.description);
    }
  }

  @override
  Future<int> createCamera(
    CameraDescription cameraDescription,
    ResolutionPreset? resolutionPreset, {
    bool enableAudio = false,
  }) async {
    try {
      if (!camerasMetadata.containsKey(cameraDescription)) {
        throw PlatformException(
          code: CameraErrorCode.missingMetadata.toString(),
          message:
              'Missing camera metadata. Make sure to call `availableCameras` before creating a camera.',
        );
      }

      final textureId = _textureCounter++;

      final cameraMetadata = camerasMetadata[cameraDescription]!;

      final cameraType = cameraMetadata.facingMode != null
          ? _cameraSettings
              .mapFacingModeToCameraType(cameraMetadata.facingMode!)
          : null;

      // Use the highest resolution possible
      // if the resolution preset is not specified.
      final videoSize = _cameraSettings
          .mapResolutionPresetToSize(resolutionPreset ?? ResolutionPreset.max);

      // Create a camera with the given audio and video constraints.
      // Sensor orientation is currently not supported.
      final camera = Camera(
        textureId: textureId,
        cameraSettings: _cameraSettings,
        options: CameraOptions(
          audio: AudioConstraints(enabled: enableAudio),
          video: VideoConstraints(
            facingMode:
                cameraType != null ? FacingModeConstraint(cameraType) : null,
            width: VideoSizeConstraint(
              ideal: videoSize.width.toInt(),
            ),
            height: VideoSizeConstraint(
              ideal: videoSize.height.toInt(),
            ),
            deviceId: cameraMetadata.deviceId,
          ),
        ),
      );

      cameras[textureId] = camera;

      return textureId;
    } on PlatformException catch (e) {
      throw CameraException(e.code, e.message);
    }
  }

  @override
  Future<void> initializeCamera(
    int cameraId, {
    // The image format group is currently not supported.
    ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown,
  }) async {
    try {
      final camera = getCamera(cameraId);

      await camera.initialize();

      // Add camera's video error events to the camera events stream.
      // The error event fires when the video element's source has failed to load, or can't be used.
      _cameraVideoErrorSubscriptions[cameraId] =
          camera.videoElement.onError.listen((html.Event _) {
        // The Event itself (_) doesn't contain information about the actual error.
        // We need to look at the HTMLMediaElement.error.
        // See: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error
        final error = camera.videoElement.error!;
        final errorCode = CameraErrorCode.fromMediaError(error);
        final errorMessage =
            error.message != '' ? error.message : _kDefaultErrorMessage;

        cameraEventStreamController.add(
          CameraErrorEvent(
            cameraId,
            'Error code: ${errorCode}, error message: ${errorMessage}',
          ),
        );
      });

      // Add camera's video abort events to the camera events stream.
      // The abort event fires when the video element's source has not fully loaded.
      _cameraVideoAbortSubscriptions[cameraId] =
          camera.videoElement.onAbort.listen((html.Event _) {
        cameraEventStreamController.add(
          CameraErrorEvent(
            cameraId,
            'Error code: ${CameraErrorCode.abort}, error message: The video element\'s source has not fully loaded.',
          ),
        );
      });

      await camera.play();

      final cameraSize = await camera.getVideoSize();

      cameraEventStreamController.add(
        CameraInitializedEvent(
          cameraId,
          cameraSize.width,
          cameraSize.height,
          // TODO(camera_web): Add support for exposure mode and point (https://github.com/flutter/flutter/issues/86857).
          ExposureMode.auto,
          false,
          // TODO(camera_web): Add support for focus mode and point (https://github.com/flutter/flutter/issues/86858).
          FocusMode.auto,
          false,
        ),
      );
    } on html.DomException catch (e) {
      throw PlatformException(code: e.name, message: e.message);
    } on CameraWebException catch (e) {
      _addCameraErrorEvent(e);
      throw PlatformException(code: e.code.toString(), message: e.description);
    }
  }

  @override
  Stream<CameraInitializedEvent> onCameraInitialized(int cameraId) {
    return _cameraEvents(cameraId).whereType<CameraInitializedEvent>();
  }

  @override
  Stream<CameraResolutionChangedEvent> onCameraResolutionChanged(int cameraId) {
    throw UnimplementedError('onCameraResolutionChanged() is not implemented.');
  }

  @override
  Stream<CameraClosingEvent> onCameraClosing(int cameraId) {
    throw UnimplementedError('onCameraClosing() is not implemented.');
  }

  @override
  Stream<CameraErrorEvent> onCameraError(int cameraId) {
    return _cameraEvents(cameraId).whereType<CameraErrorEvent>();
  }

  @override
  Stream<VideoRecordedEvent> onVideoRecordedEvent(int cameraId) {
    throw UnimplementedError('onVideoRecordedEvent() is not implemented.');
  }

  @override
  Stream<DeviceOrientationChangedEvent> onDeviceOrientationChanged() {
    throw UnimplementedError(
      'onDeviceOrientationChanged() is not implemented.',
    );
  }

  @override
  Future<void> lockCaptureOrientation(
    int cameraId,
    DeviceOrientation orientation,
  ) {
    throw UnimplementedError('lockCaptureOrientation() is not implemented.');
  }

  @override
  Future<void> unlockCaptureOrientation(int cameraId) {
    throw UnimplementedError('unlockCaptureOrientation() is not implemented.');
  }

  @override
  Future<XFile> takePicture(int cameraId) {
    try {
      return getCamera(cameraId).takePicture();
    } on html.DomException catch (e) {
      throw PlatformException(code: e.name, message: e.message);
    }
  }

  @override
  Future<void> prepareForVideoRecording() {
    throw UnimplementedError('prepareForVideoRecording() is not implemented.');
  }

  @override
  Future<void> startVideoRecording(int cameraId, {Duration? maxVideoDuration}) {
    throw UnimplementedError('startVideoRecording() is not implemented.');
  }

  @override
  Future<XFile> stopVideoRecording(int cameraId) {
    throw UnimplementedError('stopVideoRecording() is not implemented.');
  }

  @override
  Future<void> pauseVideoRecording(int cameraId) {
    throw UnimplementedError('pauseVideoRecording() is not implemented.');
  }

  @override
  Future<void> resumeVideoRecording(int cameraId) {
    throw UnimplementedError('resumeVideoRecording() is not implemented.');
  }

  @override
  Future<void> setFlashMode(int cameraId, FlashMode mode) {
    throw UnimplementedError('setFlashMode() is not implemented.');
  }

  @override
  Future<void> setExposureMode(int cameraId, ExposureMode mode) {
    throw UnimplementedError('setExposureMode() is not implemented.');
  }

  @override
  Future<void> setExposurePoint(int cameraId, Point<double>? point) {
    throw UnimplementedError('setExposurePoint() is not implemented.');
  }

  @override
  Future<double> getMinExposureOffset(int cameraId) {
    throw UnimplementedError('getMinExposureOffset() is not implemented.');
  }

  @override
  Future<double> getMaxExposureOffset(int cameraId) {
    throw UnimplementedError('getMaxExposureOffset() is not implemented.');
  }

  @override
  Future<double> getExposureOffsetStepSize(int cameraId) {
    throw UnimplementedError('getExposureOffsetStepSize() is not implemented.');
  }

  @override
  Future<double> setExposureOffset(int cameraId, double offset) {
    throw UnimplementedError('setExposureOffset() is not implemented.');
  }

  @override
  Future<void> setFocusMode(int cameraId, FocusMode mode) {
    throw UnimplementedError('setFocusMode() is not implemented.');
  }

  @override
  Future<void> setFocusPoint(int cameraId, Point<double>? point) {
    throw UnimplementedError('setFocusPoint() is not implemented.');
  }

  @override
  Future<double> getMaxZoomLevel(int cameraId) {
    throw UnimplementedError('getMaxZoomLevel() is not implemented.');
  }

  @override
  Future<double> getMinZoomLevel(int cameraId) {
    throw UnimplementedError('getMinZoomLevel() is not implemented.');
  }

  @override
  Future<void> setZoomLevel(int cameraId, double zoom) {
    throw UnimplementedError('setZoomLevel() is not implemented.');
  }

  @override
  Widget buildPreview(int cameraId) {
    return HtmlElementView(
      viewType: getCamera(cameraId).getViewType(),
    );
  }

  @override
  Future<void> dispose(int cameraId) async {
    try {
      getCamera(cameraId).dispose();
      await _cameraVideoErrorSubscriptions[cameraId]?.cancel();
      await _cameraVideoAbortSubscriptions[cameraId]?.cancel();

      cameras.remove(cameraId);
      _cameraVideoErrorSubscriptions.remove(cameraId);
      _cameraVideoAbortSubscriptions.remove(cameraId);
    } on html.DomException catch (e) {
      throw PlatformException(code: e.name, message: e.message);
    }
  }

  /// Returns a media video stream for the device with the given [deviceId].
  Future<html.MediaStream> _getVideoStreamForDevice(
    String deviceId,
  ) {
    // Create camera options with the desired device id.
    final cameraOptions = CameraOptions(
      video: VideoConstraints(deviceId: deviceId),
    );

    return _cameraSettings.getMediaStreamForOptions(cameraOptions);
  }

  /// Returns a camera for the given [cameraId].
  ///
  /// Throws a [CameraException] if the camera does not exist.
  @visibleForTesting
  Camera getCamera(int cameraId) {
    final camera = cameras[cameraId];

    if (camera == null) {
      throw PlatformException(
        code: CameraErrorCode.notFound.toString(),
        message: 'No camera found for the given camera id $cameraId.',
      );
    }

    return camera;
  }

  /// Adds a [CameraErrorEvent], associated with the [exception],
  /// to the stream of camera events.
  void _addCameraErrorEvent(CameraWebException exception) {
    cameraEventStreamController.add(
      CameraErrorEvent(
        exception.cameraId,
        'Error code: ${exception.code}, error message: ${exception.description}',
      ),
    );
  }
}
