import 'dart:async';
import 'dart:typed_data';

// import 'package:fis_measure/view/vid_painter/vid_painter.dart';
// import 'package:fis_measure/view/frame_view/native/frame_view.dart';
import 'package:fis_common/logger/logger.dart';
import 'package:fis_measure/interfaces/process/player/play_controller.dart';
import 'package:fis_measure/view/player/enums.dart';
import 'package:fis_measure/view/player/events.dart';
import 'package:flutter/material.dart' hide Image, decodeImageFromList;
import 'dart:ui';

import 'package:flyinsono/lab/pages/lab_image/widgets/image_data_player/widgets/lab_vid_painter.dart';

class LabVidPlayer extends StatefulWidget {
  const LabVidPlayer(
    this.controller, {
    Key? key,
    this.width,
    this.height,
  }) : super(key: key);

  final IPlayerController controller;

  final double? width;
  final double? height;

  @override
  State<StatefulWidget> createState() => _LabVidPlayerState();
}

class _LabVidPlayerState extends State<LabVidPlayer> {
  Uint8List? frameBytes;
  Image? image;
  Size imageSize = Size.zero;
  int frameIndex = 0;
  List<double> curColorFilterMatrix = <double>[
    1, 0, 0, 0, 0, // red
    0, 1, 0, 0, 0, // green
    0, 0, 1, 0, 0, // blue
    0, 0, 0, 1, 0, // alpha
  ];
  @override
  void initState() {
    initFrameData(
      widget.controller.currentFrame?.imageData,
      widget.controller.currentFrame?.index,
    );
    widget.controller.eventHandler.addListener(onControllerEvent);
    super.initState();
  }

  @override
  void didUpdateWidget(covariant LabVidPlayer oldWidget) {
    if (oldWidget.controller != widget.controller) {
      throw UnsupportedError("[VidTestPlayer] unsupport replace controller.");
    }
    super.didUpdateWidget(oldWidget);
  }

  void onControllerEvent(Object sender, VidPlayerEvent e) {
    if (!mounted) return;

    if (e is VidPlayerStatusChangeEvent) {
      if (!widget.controller.hasView) {
        updateFrame();
      }
    }
    if (e is VidPlayerFrameIndexChangeEvent) {
      onFrameChanged(e);
    }
    if (e is VidPlayerFilterChangeEvent) {
      onFilterMatrixChanged(e);
    }
  }

  void onFrameChanged(VidPlayerFrameIndexChangeEvent e) {
    loadFrame(e);
  }

  void onFilterMatrixChanged(VidPlayerFilterChangeEvent e) {
    setState(() {
      curColorFilterMatrix = e.filterMatrix;
    });
  }

  void loadFrame(VidPlayerFrameIndexChangeEvent e) async {
    frameIndex = e.index;
    final oldImage = image;
    final newImg = await _decodeImg(e.bytes);
    if (newImg != null) {
      if (newImg.width != imageSize.width ||
          newImg.height != imageSize.height) {
        imageSize = Size(newImg.width.toDouble(), newImg.height.toDouble());
      }
      image = newImg;
      try {
        oldImage?.dispose();
      } catch (e) {}
    }
    updateFrame();
  }

  // 获取初始帧
  void initFrameData(Uint8List? bytes, int? initIndex) async {
    if (bytes == null || initIndex == null) return;
    frameIndex = initIndex;
    final newImg = await _decodeImg(bytes);
    if (newImg != null) {
      image = newImg;
      imageSize = Size(newImg.width.toDouble(), newImg.height.toDouble());
      updateFrame();
    }
  }

  void updateFrame() {
    if (mounted) {
      setState(() {});
    }
  }

  Future<Image?> _decodeImg(Uint8List bytes) async {
    try {
      final buffer = await ImmutableBuffer.fromUint8List(bytes);
      final descriptor = await ImageDescriptor.encoded(buffer);
      final codec = await descriptor.instantiateCodec();
      final frameInfo = await codec.getNextFrame();
      codec.dispose();
      return frameInfo.image;
    } catch (e) {
      logger.e("Decode player frame error", e);
      return null;
    }
  }

  @override
  Widget build(BuildContext context) {
    Widget? child;
    switch (widget.controller.status) {
      case VidPlayStatus.init:
        child = Container();
        break;
      case VidPlayStatus.ready:
        child = Container();
        break;
      case VidPlayStatus.loadFail:
        child = Container();
        break;
      case VidPlayStatus.play:
      case VidPlayStatus.pause:
        child = buildFrameView(context);
        break;
      case VidPlayStatus.stop:
      case VidPlayStatus.dispose:
        child = const Text("Closed");
        break;
    }
    return buildBox(context, child);
  }

  Widget buildBox(BuildContext context, Widget child) {
    return Container(
      alignment: Alignment.center,
      child: child,
    );
  }

  Widget buildFrameView(BuildContext context) {
    if (image != null) {
      return RepaintBoundary(
        child: SizedBox.expand(
          child: FittedBox(
            child: CustomPaint(
              painter: LabVidPainter(
                image: image!,
                frameIndex: frameIndex,
                colorFilterMatrix: curColorFilterMatrix,
              ),
              isComplex: false, //是否为复杂图像（true会缓存）
              size: imageSize,
            ),
          ),
        ),
      );
    } else {
      return Container();
    }
  }

  @override
  void dispose() {
    widget.controller.eventHandler.removeListener(onControllerEvent);
    super.dispose();
  }
}
