// 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:typed_data';

import 'package:ui/ui.dart' as ui;

import 'browser_detection.dart';
import 'dom.dart';
import 'safe_browser_api.dart';
import 'util.dart';

Object? get _jsImageDecodeFunction => getJsProperty<Object?>(
  getJsProperty<Object>(
    getJsProperty<Object>(domWindow, 'Image'),
    'prototype',
  ),
  'decode',
);
final bool _supportsDecode = _jsImageDecodeFunction != null;

typedef WebOnlyImageCodecChunkCallback = void Function(
    int cumulativeBytesLoaded, int expectedTotalBytes);

class HtmlCodec implements ui.Codec {
  HtmlCodec(this.src, {this.chunkCallback});

  final String src;
  final WebOnlyImageCodecChunkCallback? chunkCallback;

  @override
  int get frameCount => 1;

  @override
  int get repetitionCount => 0;

  @override
  Future<ui.FrameInfo> getNextFrame() async {
    final Completer<ui.FrameInfo> completer = Completer<ui.FrameInfo>();
    // Currently there is no way to watch decode progress, so
    // we add 0/100 , 100/100 progress callbacks to enable loading progress
    // builders to create UI.
      chunkCallback?.call(0, 100);
    if (_supportsDecode) {
      final DomHTMLImageElement imgElement = createDomHTMLImageElement();
      imgElement.src = src;
      setJsProperty<String>(imgElement, 'decoding', 'async');

      // Ignoring the returned future on purpose because we're communicating
      // through the `completer`.
      // ignore: unawaited_futures
      imgElement.decode().then((dynamic _) {
        chunkCallback?.call(100, 100);
        int naturalWidth = imgElement.naturalWidth.toInt();
        int naturalHeight = imgElement.naturalHeight.toInt();
        // Workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=700533.
        if (naturalWidth == 0 && naturalHeight == 0 && browserEngine == BrowserEngine.firefox) {
          const int kDefaultImageSizeFallback = 300;
          naturalWidth = kDefaultImageSizeFallback;
          naturalHeight = kDefaultImageSizeFallback;
        }
        final HtmlImage image = HtmlImage(
          imgElement,
          naturalWidth,
          naturalHeight,
        );
        completer.complete(SingleFrameInfo(image));
      }).catchError((dynamic e) {
        // This code path is hit on Chrome 80.0.3987.16 when too many
        // images are on the page (~1000).
        // Fallback here is to load using onLoad instead.
        _decodeUsingOnLoad(completer);
      });
    } else {
      _decodeUsingOnLoad(completer);
    }
    return completer.future;
  }

  void _decodeUsingOnLoad(Completer<ui.FrameInfo> completer) {
    final DomHTMLImageElement imgElement = createDomHTMLImageElement();
    // If the browser doesn't support asynchronous decoding of an image,
    // then use the `onload` event to decide when it's ready to paint to the
    // DOM. Unfortunately, this will cause the image to be decoded synchronously
    // on the main thread, and may cause dropped framed.
    late DomEventListener errorListener;
    DomEventListener? loadListener;
    errorListener = allowInterop((DomEvent event) {
      if (loadListener != null) {
        imgElement.removeEventListener('load', loadListener);
      }
      imgElement.removeEventListener('error', errorListener);
      completer.completeError(event);
    });
    imgElement.addEventListener('error', errorListener);
    loadListener = allowInterop((DomEvent event) {
      if (chunkCallback != null) {
        chunkCallback!(100, 100);
      }
      imgElement.removeEventListener('load', loadListener);
      imgElement.removeEventListener('error', errorListener);
      final HtmlImage image = HtmlImage(
        imgElement,
        imgElement.naturalWidth.toInt(),
        imgElement.naturalHeight.toInt(),
      );
      completer.complete(SingleFrameInfo(image));
    });
    imgElement.addEventListener('load', loadListener);
    imgElement.src = src;
  }

  @override
  void dispose() {}
}

class HtmlBlobCodec extends HtmlCodec {
  HtmlBlobCodec(this.blob) : super(domWindow.URL.createObjectURL(blob));

  final DomBlob blob;

  @override
  void dispose() {
    domWindow.URL.revokeObjectURL(src);
  }
}

class SingleFrameInfo implements ui.FrameInfo {
  SingleFrameInfo(this.image);

  @override
  Duration get duration => Duration.zero;

  @override
  final ui.Image image;
}

class HtmlImage implements ui.Image {
  HtmlImage(this.imgElement, this.width, this.height) {
    ui.Image.onCreate?.call(this);
  }

  final DomHTMLImageElement imgElement;
  bool _didClone = false;

  bool _disposed = false;
  @override
  void dispose() {
    ui.Image.onDispose?.call(this);
    // Do nothing. The codec that owns this image should take care of
    // releasing the object url.
    if (assertionsEnabled) {
      _disposed = true;
    }
  }

  @override
  bool get debugDisposed {
    if (assertionsEnabled) {
      return _disposed;
    }
    return throw StateError('Image.debugDisposed is only available when asserts are enabled.');
  }


  @override
  ui.Image clone() => this;

  @override
  bool isCloneOf(ui.Image other) => other == this;

  @override
  List<StackTrace>? debugGetOpenHandleStackTraces() => null;

  @override
  final int width;

  @override
  final int height;

  @override
  Future<ByteData?> toByteData({ui.ImageByteFormat format = ui.ImageByteFormat.rawRgba}) {
    switch (format) {
      // TODO(ColdPaleLight): https://github.com/flutter/flutter/issues/89128
      // The format rawRgba always returns straight rather than premul currently.
      case ui.ImageByteFormat.rawRgba:
      case ui.ImageByteFormat.rawStraightRgba:
        final DomCanvasElement canvas = createDomCanvasElement()
          ..width = width.toDouble()
          ..height = height.toDouble();
        final DomCanvasRenderingContext2D ctx = canvas.context2D;
        ctx.drawImage(imgElement, 0, 0);
        final DomImageData imageData = ctx.getImageData(0, 0, width, height);
        return Future<ByteData?>.value(imageData.data.buffer.asByteData());
      default:
        if (imgElement.src?.startsWith('data:') ?? false) {
          final UriData data = UriData.fromUri(Uri.parse(imgElement.src!));
          return Future<ByteData?>.value(data.contentAsBytes().buffer.asByteData());
        } else {
          return Future<ByteData?>.value();
        }
    }
  }

  DomHTMLImageElement cloneImageElement() {
    if (!_didClone) {
      _didClone = true;
      imgElement.style.position = 'absolute';
    }
    return imgElement.cloneNode(true) as DomHTMLImageElement;
  }

  @override
  String toString() => '[$width\u00D7$height]';
}
