import 'package:fis_measure/interfaces/process/workspace/exam_info.dart';
import 'package:fis_measure/interfaces/process/workspace/measure_controller.dart';
import 'package:fis_measure/process/workspace/application.dart';
import 'package:fis_measure/view/player/controller.dart';
import 'package:fis_measure/view/player/enums.dart';
import 'package:fis_measure/view/player/events.dart';
import 'package:fis_vid/data_host/data_host.dart';

import 'package:fis_measure/interfaces/process/workspace/application.dart';
import 'package:fis_measure/interfaces/process/player/play_controller.dart';
import 'package:fis_measure/interfaces/process/config/style_config.dart';
import 'package:fis_common/event/event_type.dart';
import 'package:get/get.dart';
import 'package:vid/us/vid_us_2d_visual.dart';
import 'package:vid/us/vid_us_image.dart';
import 'package:vid/us/vid_us_visual_area_type.dart';

typedef MeasureImagesFetchFunc = Future<List<ExamImageInfo>> Function(
    String code);

class MeasureController implements IMeasureController {
  late final ExamInfo _examInfo;
  VidDataHost? _vidDataHost;
  IPlayerController? _playerController;
  IApplication? _application;
  late final MeasureImagesFetchFunc _imagesFetchFunc;

  MeasureController(String code,
      {required MeasureImagesFetchFunc imagesFetchFunc}) {
    _examInfo = ExamInfo(code);
    _imagesFetchFunc = imagesFetchFunc;
  }

  @override
  ExamInfo get examInfo => _examInfo;

  @override
  String get currentVidUrl => examInfo.selectedImage.url;

  @override
  VidDataHost get dataHost => _vidDataHost!;

  @override
  bool get canDoMeasure => playerController.status == VidPlayStatus.pause;

  @override
  IPlayerController get playerController => _playerController!;

  @override
  // TODO: implement styleConfiguration
  IStyeConfiguration get styleConfiguration => throw UnimplementedError();

  @override
  IApplication get workingApplication => _application!;

  @override
  var imageLoaded = FEventHandler<ExamImageInfo?>();

  @override
  Future<void> load() async {
    final images = await _imagesFetchFunc.call(examInfo.code);
    examInfo.images.addAll(images);
    examInfo.selectedImageChanged.addListener(_onExamImageSelectedChanged);
    // // 加载第一张图像
    // examInfo.selectedImageIndex = 0;
  }

  @override
  void dispose() {
    examInfo.selectedImageChanged.removeListener(_onExamImageSelectedChanged);
    Get.delete<IApplication>();
    Get.delete<IPlayerController>();
    _vidDataHost?.release();
  }

  void _onExamImageSelectedChanged(Object sender, int index) {
    final url = currentVidUrl;
    if (_playerController != null) {
      playerController.eventHandler.removeListener(_onPlayerEnvent);
      playerController.dispose();
    }
    if (_vidDataHost != null) {
      dataHost.frameLoaded.removeListener(_onFrameLoaded);
    }

    _vidDataHost = VidDataHost(url);
    _playerController =
        Get.put<IPlayerController>(VidPlayerController(dataHost: dataHost));

    dataHost.frameLoaded.addListener(_onFrameLoaded);
    dataHost.load().then((value) {
      if (value == null) {
        // TOOO: add log
      }
      _application = Get.put<IApplication>(Application(_vidDataHost!.probe));
      playerController.eventHandler.addListener(_onPlayerEnvent);
      // 立即播放
      playerController.setLoadState(value != null);
      Future.delayed(const Duration(milliseconds: 100), () {
        playerController.play();
      });

      imageLoaded.emit(sender, examInfo.selectedImage);
    });
  }

  void _onFrameLoaded(Object sender, VidUsImage frame) {
    workingApplication.loadFrame(frame);
  }

  void _onPlayerEnvent(Object sender, VidPlayerEvent e) {
    if (e is VidPlayerStatusChangeEvent) {
      workingApplication.canMeasure = e.status == VidPlayStatus.pause;
    }
  }
}
