import 'dart:async';
import 'dart:html';
import 'dart:typed_data';
import 'dart:math' as math;

/// 压缩图片
/// [jpegBytes] 图片字节
/// [quality] 压缩质量 0-100
Future<Uint8List> compressImage(
    Uint8List jpegBytes, int quality, int minSize) async {
  final ImageElement image = await _decodeJpeg(jpegBytes);

  final double scale = _calcScale(
    srcWidth: image.width!.toDouble(),
    srcHeight: image.height!.toDouble(),
    minWidth: minSize.toDouble(),
    minHeight: minSize.toDouble(),
  );
  final scaledWidth = image.width! ~/ scale;
  final scaledHeight = image.height! ~/ scale;
  // 创建一个 canvas 元素
  final CanvasElement canvas =
      CanvasElement(width: scaledWidth, height: scaledHeight);

  // 将图像绘制到 canvas 上
  final CanvasRenderingContext2D context =
      canvas.getContext('2d') as CanvasRenderingContext2D;
  context.drawImageScaled(image, 0, 0, scaledWidth, scaledHeight);

  // 将 canvas 转换为 Blob 对象
  final blob = await canvas.toBlob('image/jpeg', quality / 100);

  // 将 Blob 对象转换为 Uint8List
  final reader = FileReader();
  final completer = Completer<Uint8List>();

  reader.onLoadEnd.listen(
      (e) => completer.complete(nativeUint8ListToUint8List(reader.result)));
  reader.readAsArrayBuffer(blob);

  return completer.future;
}

Uint8List nativeUint8ListToUint8List(Object? nativeUint8List) {
  return Uint8List.fromList(List<int>.from(nativeUint8List as List<dynamic>));
}

Future<ImageElement> _decodeJpeg(Uint8List jpegBytes) async {
  // 将 JPEG 字节列表转换为 Blob 对象
  final blob = Blob([jpegBytes], 'image/jpeg');

  // 创建一个 ImageElement 元素
  final image = ImageElement();

  // 创建一个 Completer，以便在图像加载完成时进行回调
  final completer = Completer<ImageElement>();

  // 当图像加载完成时，将 ImageElement 元素返回到 Completer 中
  image.onLoad.listen((event) => completer.complete(image));

  // 加载图像
  image.src = Url.createObjectUrlFromBlob(blob);

  return completer.future;
}

double _calcScale({
  required double srcWidth,
  required double srcHeight,
  required double minWidth,
  required double minHeight,
}) {
  var scaleW = srcWidth / minWidth;
  var scaleH = srcHeight / minHeight;
  var scale = math.max(1.0, math.min(scaleW, scaleH));
  return scale;
}
