// 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 'package:flutter/foundation.dart' show visibleForTesting;
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
import 'package:image_picker_for_web/src/image_resizer.dart';
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';

final String _kImagePickerInputsDomId = '__image_picker_web-file-input';
final String _kAcceptImageMimeType = 'image/*';
final String _kAcceptVideoMimeType = 'video/3gpp,video/x-m4v,video/mp4,video/*';

/// The web implementation of [ImagePickerPlatform].
///
/// This class implements the `package:image_picker` functionality for the web.
class ImagePickerPlugin extends ImagePickerPlatform {
  final ImagePickerPluginTestOverrides? _overrides;

  bool get _hasOverrides => _overrides != null;

  late html.Element _target;

  late ImageResizer _imageResizer;

  /// A constructor that allows tests to override the function that creates file inputs.
  ImagePickerPlugin({
    @visibleForTesting ImagePickerPluginTestOverrides? overrides,
    @visibleForTesting ImageResizer? imageResizer,
  }) : _overrides = overrides {
    _imageResizer = imageResizer ?? ImageResizer();
    _target = _ensureInitialized(_kImagePickerInputsDomId);
  }

  /// Registers this class as the default instance of [ImagePickerPlatform].
  static void registerWith(Registrar registrar) {
    ImagePickerPlatform.instance = ImagePickerPlugin();
  }

  /// Returns a [PickedFile] with the image that was picked.
  ///
  /// The `source` argument controls where the image comes from. This can
  /// be either [ImageSource.camera] or [ImageSource.gallery].
  ///
  /// Note that the `maxWidth`, `maxHeight` and `imageQuality` arguments are not supported on the web. If any of these arguments is supplied, it'll be silently ignored by the web version of the plugin.
  ///
  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
  /// Defaults to [CameraDevice.rear].
  ///
  /// If no images were picked, the return value is null.
  @override
  Future<PickedFile> pickImage({
    required ImageSource source,
    double? maxWidth,
    double? maxHeight,
    int? imageQuality,
    CameraDevice preferredCameraDevice = CameraDevice.rear,
  }) {
    String? capture = computeCaptureAttribute(source, preferredCameraDevice);
    return pickFile(accept: _kAcceptImageMimeType, capture: capture);
  }

  /// Returns a [PickedFile] containing the video that was picked.
  ///
  /// The [source] argument controls where the video comes from. This can
  /// be either [ImageSource.camera] or [ImageSource.gallery].
  ///
  /// Note that the `maxDuration` argument is not supported on the web. If the argument is supplied, it'll be silently ignored by the web version of the plugin.
  ///
  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
  /// Defaults to [CameraDevice.rear].
  ///
  /// If no images were picked, the return value is null.
  @override
  Future<PickedFile> pickVideo({
    required ImageSource source,
    CameraDevice preferredCameraDevice = CameraDevice.rear,
    Duration? maxDuration,
  }) {
    String? capture = computeCaptureAttribute(source, preferredCameraDevice);
    return pickFile(accept: _kAcceptVideoMimeType, capture: capture);
  }

  /// Injects a file input with the specified accept+capture attributes, and
  /// returns the PickedFile that the user selected locally.
  ///
  /// `capture` is only supported in mobile browsers.
  /// See https://caniuse.com/#feat=html-media-capture
  @visibleForTesting
  Future<PickedFile> pickFile({
    String? accept,
    String? capture,
  }) {
    html.FileUploadInputElement input =
        createInputElement(accept, capture) as html.FileUploadInputElement;
    _injectAndActivate(input);
    return _getSelectedFile(input);
  }

  /// Returns an [XFile] with the image that was picked.
  ///
  /// The `source` argument controls where the image comes from. This can
  /// be either [ImageSource.camera] or [ImageSource.gallery].
  ///
  /// Note that the `maxWidth`, `maxHeight` and `imageQuality` arguments are not supported on the web. If any of these arguments is supplied, it'll be silently ignored by the web version of the plugin.
  ///
  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
  /// Defaults to [CameraDevice.rear].
  ///
  /// If no images were picked, the return value is null.
  @override
  Future<XFile> getImage({
    required ImageSource source,
    double? maxWidth,
    double? maxHeight,
    int? imageQuality,
    CameraDevice preferredCameraDevice = CameraDevice.rear,
  }) async {
    String? capture = computeCaptureAttribute(source, preferredCameraDevice);
    List<XFile> files = await getFiles(
      accept: _kAcceptImageMimeType,
      capture: capture,
    );
    return _imageResizer.resizeImageIfNeeded(
      files.first,
      maxWidth,
      maxHeight,
      imageQuality,
    );
  }

  /// Returns an [XFile] containing the video that was picked.
  ///
  /// The [source] argument controls where the video comes from. This can
  /// be either [ImageSource.camera] or [ImageSource.gallery].
  ///
  /// Note that the `maxDuration` argument is not supported on the web. If the argument is supplied, it'll be silently ignored by the web version of the plugin.
  ///
  /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera].
  /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device.
  /// Defaults to [CameraDevice.rear].
  ///
  /// If no images were picked, the return value is null.
  @override
  Future<XFile> getVideo({
    required ImageSource source,
    CameraDevice preferredCameraDevice = CameraDevice.rear,
    Duration? maxDuration,
  }) async {
    String? capture = computeCaptureAttribute(source, preferredCameraDevice);
    List<XFile> files = await getFiles(
      accept: _kAcceptVideoMimeType,
      capture: capture,
    );
    return files.first;
  }

  /// Injects a file input, and returns a list of XFile that the user selected locally.
  @override
  Future<List<XFile>> getMultiImage({
    double? maxWidth,
    double? maxHeight,
    int? imageQuality,
  }) async {
    final List<XFile> images = await getFiles(
      accept: _kAcceptImageMimeType,
      multiple: true,
    );
    final Iterable<Future<XFile>> resized = images.map(
      (image) => _imageResizer.resizeImageIfNeeded(
        image,
        maxWidth,
        maxHeight,
        imageQuality,
      ),
    );

    return Future.wait<XFile>(resized);
  }

  /// Injects a file input with the specified accept+capture attributes, and
  /// returns a list of XFile that the user selected locally.
  ///
  /// `capture` is only supported in mobile browsers.
  ///
  /// `multiple` can be passed to allow for multiple selection of files. Defaults
  /// to false.
  ///
  /// See https://caniuse.com/#feat=html-media-capture
  @visibleForTesting
  Future<List<XFile>> getFiles({
    String? accept,
    String? capture,
    bool multiple = false,
  }) {
    html.FileUploadInputElement input = createInputElement(
      accept,
      capture,
      multiple: multiple,
    ) as html.FileUploadInputElement;
    _injectAndActivate(input);

    return _getSelectedXFiles(input);
  }

  // DOM methods

  /// Converts plugin configuration into a proper value for the `capture` attribute.
  ///
  /// See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#capture
  @visibleForTesting
  String? computeCaptureAttribute(ImageSource source, CameraDevice device) {
    if (source == ImageSource.camera) {
      return (device == CameraDevice.front) ? 'user' : 'environment';
    }
    return null;
  }

  List<html.File>? _getFilesFromInput(html.FileUploadInputElement input) {
    if (_hasOverrides) {
      return _overrides!.getMultipleFilesFromInput(input);
    }
    return input.files;
  }

  /// Handles the OnChange event from a FileUploadInputElement object
  /// Returns a list of selected files.
  List<html.File>? _handleOnChangeEvent(html.Event event) {
    final html.FileUploadInputElement input =
        event.target as html.FileUploadInputElement;
    return _getFilesFromInput(input);
  }

  /// Monitors an <input type="file"> and returns the selected file.
  Future<PickedFile> _getSelectedFile(html.FileUploadInputElement input) {
    final Completer<PickedFile> _completer = Completer<PickedFile>();
    // Observe the input until we can return something
    input.onChange.first.then((event) {
      final files = _handleOnChangeEvent(event);
      if (!_completer.isCompleted && files != null) {
        _completer.complete(PickedFile(
          html.Url.createObjectUrl(files.first),
        ));
      }
    });
    input.onError.first.then((event) {
      if (!_completer.isCompleted) {
        _completer.completeError(event);
      }
    });
    // Note that we don't bother detaching from these streams, since the
    // "input" gets re-created in the DOM every time the user needs to
    // pick a file.
    return _completer.future;
  }

  /// Monitors an <input type="file"> and returns the selected file(s).
  Future<List<XFile>> _getSelectedXFiles(html.FileUploadInputElement input) {
    final Completer<List<XFile>> _completer = Completer<List<XFile>>();
    // Observe the input until we can return something
    input.onChange.first.then((event) {
      final files = _handleOnChangeEvent(event);
      if (!_completer.isCompleted && files != null) {
        _completer.complete(files.map((file) {
          return XFile(
            html.Url.createObjectUrl(file),
            name: file.name,
            length: file.size,
            lastModified: DateTime.fromMillisecondsSinceEpoch(
              file.lastModified ?? DateTime.now().millisecondsSinceEpoch,
            ),
            mimeType: file.type,
          );
        }).toList());
      }
    });
    input.onError.first.then((event) {
      if (!_completer.isCompleted) {
        _completer.completeError(event);
      }
    });
    // Note that we don't bother detaching from these streams, since the
    // "input" gets re-created in the DOM every time the user needs to
    // pick a file.
    return _completer.future;
  }

  /// Initializes a DOM container where we can host input elements.
  html.Element _ensureInitialized(String id) {
    var target = html.querySelector('#${id}');
    if (target == null) {
      final html.Element targetElement =
          html.Element.tag('flt-image-picker-inputs')..id = id;

      html.querySelector('body')!.children.add(targetElement);
      target = targetElement;
    }
    return target;
  }

  /// Creates an input element that accepts certain file types, and
  /// allows to `capture` from the device's cameras (where supported)
  @visibleForTesting
  html.Element createInputElement(
    String? accept,
    String? capture, {
    bool multiple = false,
  }) {
    if (_hasOverrides) {
      return _overrides!.createInputElement(accept, capture);
    }

    html.Element element = html.FileUploadInputElement()
      ..accept = accept
      ..multiple = multiple;

    if (capture != null) {
      element.setAttribute('capture', capture);
    }

    return element;
  }

  /// Injects the file input element, and clicks on it
  void _injectAndActivate(html.Element element) {
    _target.children.clear();
    _target.children.add(element);
    element.click();
  }
}

// Some tools to override behavior for unit-testing
/// A function that creates a file input with the passed in `accept` and `capture` attributes.
@visibleForTesting
typedef OverrideCreateInputFunction = html.Element Function(
  String? accept,
  String? capture,
);

/// A function that extracts list of files from the file `input` passed in.
@visibleForTesting
typedef OverrideExtractMultipleFilesFromInputFunction = List<html.File>
    Function(html.Element? input);

/// Overrides for some of the functionality above.
@visibleForTesting
class ImagePickerPluginTestOverrides {
  /// Override the creation of the input element.
  late OverrideCreateInputFunction createInputElement;

  /// Override the extraction of the selected files from an input element.
  late OverrideExtractMultipleFilesFromInputFunction getMultipleFilesFromInput;
}
