import 'package:fis_measure/view/gesture/positioned_cursor.dart';
import 'package:fis_measure/view/measure/measure_config/widgets/measure_configuration_style.dart';
import 'package:fis_measure/interfaces/process/items/item.dart';
import 'package:fis_measure/process/workspace/measure_data_controller.dart';
import 'package:fis_jsonrpc/rpc.dart' hide DRect;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flyinsono/lab/manager/interfaces/measure.dart';
import 'package:flyinsono/lab/mock_data/mock_rpc.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/image_measure_overlay/widgets/rim_measure_result_table.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/image_operate_panel/controller.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/image_operate_panel/widgets/measure_config/measure_configuration_style.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/vid_ui_repaint_overlay/controller.dart';
import 'package:flyinsono/pages/measure/helpers/measureData_helper.dart';
import 'package:flyinsono/rpc.dart';
import 'package:get/get.dart';
import 'dart:async';
import 'package:fis_measure/process/workspace/application.dart';
import 'package:fis_measure/interfaces/process/items/item_metas.dart';
import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
import 'package:fis_measure/process/workspace/cross_frame.dart';
import 'package:fis_measure/process/layout/configuration.dart';
import 'package:fis_measure/interfaces/process/workspace/application.dart';
import 'package:vid/us/vid_us_probe.dart';
import 'package:vid/us/vid_us_image.dart';
import 'package:vid/us/vid_us_visual_area_type.dart';
import 'package:fis_measure/interfaces/date_types/rect_region.dart';
import 'package:fis_measure/interfaces/date_types/rect.dart';
import 'package:vid/us/vid_us_mode.dart';
import 'package:fis_measure/process/workspace/urm/application.dart';
import 'package:fis_measure/interfaces/process/visuals/visual_area.dart';
import 'package:fis_measure/interfaces/enums/items.dart';
import 'package:fis_measure/process/items/top_item.dart';
import 'package:fis_measure/interfaces/process/urm/urm_data_processor.dart';
import 'package:fis_measure/process/primitives/utils/urm_sharp_copy.dart';
import 'package:vid/us/vid_us_2d_visual.dart';
import 'package:vid/us/vid_us_logical_coordinate.dart';
import 'package:fis_measure/process/visual/v2d_visual.dart';

class ImageMeasureOverlayController extends GetxController {
  ImageMeasureOverlayController({
    required this.onWorkingChildChanged,
    required this.onCrossFramesChanged,
    required this.onCrossFramesTriggered,
    required this.onCrossFramesOver,
    required this.onVisualAreaChanged,
    required this.onMeasureItemChanged,
    this.onUpdateChart,
    this.onUpdateRimResult,
    this.onUpdatePerfusion,
    this.onMeasureFinishedOnce,
  });

  final ValueChanged<int> onWorkingChildChanged;
  final ValueChanged<List<int>> onCrossFramesChanged;
  final ValueChanged<CrossFrameContext> onCrossFramesTriggered;
  final ValueChanged<CrossFrameContext> onCrossFramesOver;
  final ValueChanged<URMChartParams>? onUpdateChart;
  final ValueChanged<URMRimMesureResult?>? onUpdateRimResult;
  final ValueChanged<int>? onUpdatePerfusion;
  final ValueChanged<bool>? onMeasureItemChanged; // 测量项变更完毕事件
  final ValueChanged<bool>? onMeasureFinishedOnce; // 测量结束事件

  final ValueChanged<String> onVisualAreaChanged;

  static const String imageMeasureOverlayId = "image_measure_overlay";

  static const String activeCanvasLayerId =
      "active_canvas_layer"; // 活动的测量画布 updateRenderReady 事件来到需要更新
  static const String recordCanvasLayerId =
      "record_canvas_layer"; // 记录历史的画布 measureSystemSettingChanged 事件来到需要更新 updateRenderReady 事件来到需要更新
  static const String annotationRecordCanvasLayerId =
      "annotation_record_canvas_layer"; // 记录历史的画布 measureSystemSettingChanged 事件来到需要更新 updateRenderReady 事件来到需要更新

  static const String mouseGestureLayerId = "mouse_gesture_layer"; // 手势监听层
  static const String measureResultLayerId = "measure_result_layer"; // 测量结果层
  static const String accessibilityLayerId = "accessibility_layer"; // 辅助功能层
  static const String sharpCopySectionLayerId =
      "sharp_copy_section_layer"; // URM复制框层
  static const String sharpCopyToolLayerId =
      "sharp_copy_tool_layer"; // URM复制框工具层
  static const String rimMeasureResultTableId =
      "rimMeasure_result_table"; // rim测量的结果值

  ///比例尺

  ///图像类型
  ImageType imageType = ImageType.URM;

  /// 图片的宽高比（用于对齐图像）
  double aspectRatio = 16 / 9;

  IApplication? app;

  // App 缓存
  // IApplication? cacheApp;

  MeasureDataController? measureDataController;
  IMouseState? mouseState;

  /// 跨图测量原始图像索引
  int? crossImageBaseIndex;

  VidUsProbe? _probe;
  String? _imageUrl;
  int? _imageCount;

  CrossFrameContext? _crossFrameContext;

  bool ifContainerTissueTM = false;
  RectRegion tissueTMPixelRegion = RectRegion();

  final List<int> _crossFrameIndexList = [];

  /// 面板的 key
  final GlobalKey imageMeasureLayerKey = GlobalKey();

  bool isActive = false; // 是否激活

  // 显示辅助功能面板
  bool showAccessibility = false;
  // 是否是注释
  bool isAnnotation = false;

  /// rim结构化结果
  List<RimMeasureRowResult> rimMeasureResultList = [];

  //图像区域的宽度（包含黑边）
  static double imageAreaWidth = 0;

  ///图像宽度（双幅的取一个宽度）单位cm
  static double imageWidth = 0;
  final measureManager = Get.find<IMeasureManager>();

  void active() {
    isActive = true;
    update([imageMeasureOverlayId]);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      updateApplicationDisplaySize();
    });
  }

  void deactive() {
    isActive = false;
    update([imageMeasureOverlayId]);
    _disableAccessibility();
  }

  /// 测量样式变更
  void updateMeasureStyle() {
    update([measureResultLayerId, recordCanvasLayerId]);
  }

  void setMeasureLayerSize(int width, int height) {
    aspectRatio = width / height;
    update([imageMeasureOverlayId]);
    // 下一帧再更新
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      updateApplicationDisplaySize();
    });
  }

  /// 响应切换测量项
  void changeMeasureItem(ItemMeta itemMeta) {
    final application = Get.find<IApplication>();
    bool success = application.switchItem(itemMeta);
    final item = application.activeMeasureItem!;
    if (item is ITopMeasureItem) {
      item.switchChild(0);
      onWorkingChildChanged(0);
      item.workingChildChanged.addListener(_onWorkingChildChanged);
    }
    onMeasureItemChanged?.call(success);
  }

  /// 子测量项变化事件监听
  void _onWorkingChildChanged(sender, int e) {
    onWorkingChildChanged(e);
  }

  /// 更新 rim
  void updateRimResult(URMRimMesureResult? mesureresult) {
    if (mesureresult == null) return;

    rimMeasureResultList = [];
    rimMeasureResultList =
        measureManager.handleMesureresult(mesureresult: mesureresult);

    update([rimMeasureResultTableId]);
  }

  void changeChildMeasureItem(int selectIndex) {
    final application = Get.find<IApplication>();
    final item = application.activeMeasureItem!;
    if (item is ITopMeasureItem) {
      item.switchChild(selectIndex);
    }
  }

  // 计算实际render的尺寸，赋值给 application.displaySize
  void updateApplicationDisplaySize() {
    // 根据key获取到实际渲染尺寸
    if (imageMeasureLayerKey.currentContext == null) return;
    final RenderBox renderBox =
        imageMeasureLayerKey.currentContext!.findRenderObject() as RenderBox;
    final size = renderBox.size;
    try {
      final application = Get.find<IApplication>();
      application.displaySize = size;
      _findMultiRegions();
    } catch (e) {
      print(e);
    }
  }

  // 只更新 Application 的显示尺寸
  void _updateApplicationDisplaySizeOnly() {
    if (imageMeasureLayerKey.currentContext == null) return;
    final RenderBox renderBox =
        imageMeasureLayerKey.currentContext!.findRenderObject() as RenderBox;
    final size = renderBox.size;
    try {
      final application = Get.find<IApplication>();
      application.displaySize = size;
    } catch (e) {
      print(e);
    }
  }

  MeasureModeSelection getMeasureModeSelection(VidUsImage? vidUsImage) {
    final application = Get.find<IApplication>();
    List<String> getModes = [];
    if (vidUsImage != null) {
      for (var element in vidUsImage.visuals.first.modes) {
        getModes.add(element.type.toString().split('.')[1]);
      }
    }
    getModes.add("URM");
    return MeasureModeSelection(
      application.applicationName,
      application.categoryName,
      application.isThirdPart ? ['TPPTissue'] : getModes,
    );
  }

  List<VidUsMode> setApplicationModes(VidUsImage? vidUsImage) {
    List<VidUsMode> applicationModes = [];
    if (vidUsImage != null) {
      applicationModes = vidUsImage.visuals.first.modes;
    }
    return applicationModes;
  }

  @override
  void onInit() {
    super.onInit();
    mouseState = MouseState();
    Get.put<IMouseState>(mouseState!); // TODO remove
  }

  @override
  void onReady() {
    super.onReady();
  }

  /// 初始化卡尺样式部分
  Future<void> _initMouseModuel() async {
    // FIXME 优化各个组件，尽可能脱离 MeasureDataController 使用
    measureDataController =
        Get.put<MeasureDataController>(MeasureDataController(
      MeasureDataHelper.saveImage,
    ));
    MeasureSystemSettingDTO settings =
        await MeasureDataHelper.getMeasureSystemSettingAsync();
    if (measureDataController != null) {
      measureDataController!.measureSystemSetting = settings;
      measureDataController!.checkErrorUnitConfig();
      measureDataController!.checkErrorStyleConfig();

      measureDataController!
          .checkCursorColor(StyleConfig.C_MEASURE_CURSOR_COLOR[0]);
    }
    mouseState!.cursorType =
        getMeasureSystemSettingCursorType(settings.cursorType);
    mouseState!.cursorSize = settings.cursorSize.toDouble();
  }

  Future<void> buildApplication(
    VidUsProbe probe,
    int imageCount, {
    required String url,
  }) async {
    _probe = probe;
    _imageUrl = url;
    _imageCount = imageCount;
    await LayoutConfiguration.ins.loadData();
    _initMouseModuel();
    if (app != null) {
      // app!.imageUrl = _imageUrl;
      // final isPass = _checkAndHandleCrossImage();
      // onCrossFramesChanged.call(_crossFrameIndexList); // 更新跨帧指示器
      // if (!isPass) {
      //   // 仅切图
      //   return;
      // }

      // TODO: 暂时不支持跨图
      _crossFrameIndexList.clear();
      onCrossFramesChanged.call(_crossFrameIndexList); // 更新跨帧指示器
      _crossFrameContext = null;

      _disposeCurrentApp();
    }
    _buildNewApp();
    _updateApplicationDisplaySizeOnly();
    app!.imageUrl = _imageUrl;
    app!.crossFrameTriggered.addListener(_onCrossFrameTriggered);
    app!.crossFrameAdded.addListener(_onCrossFrameAdded);
    if (_crossFrameContext != null) {
      // 传递跨帧上下文
      app!.crossFrameContext = _crossFrameContext;
    }
  }

  void _disposeCurrentApp() {
    // app!.visualsLoaded.removeListener(onVisualsLoaded);
    app!.updateRenderReady.removeListener(_onMeasureRerenderReady);
    app!.visualAreaChanged.removeListener(_visualAreaChanged);
    app!.activeMeasureItemChanged.removeListener(_onActiveMeasureItemChanged);
    final item = app!.activeMeasureItem;
    if (item != null && item is ITopMeasureItem) {
      item.workingChildChanged.removeListener(_onWorkingChildChanged);
    }
    UrmSharpCopyBoard.typeCacheChanged
        .removeListener(onUrmSharpCopyCacheChanged);
    UrmSharpCopyBoard.activeStateChanged
        .removeListener(onUrmSharpCopyActiveStateChanged);
  }

  void _buildNewApp() {
    app = Application(_probe!);
    Get.delete<IApplication>();
    Get.put<IApplication>(app!);
    app!.isSingleFrame = _imageCount == 1;

    update([imageMeasureOverlayId]);
    app!.updateRenderReady.addListener(_onMeasureRerenderReady);
    app!.visualAreaChanged.addListener(_visualAreaChanged);
    app!.activeMeasureItemChanged.addListener(_onActiveMeasureItemChanged);
    // app!.visualsLoaded.addListener(onVisualsLoaded);
    UrmSharpCopyBoard.typeCacheChanged.addListener(onUrmSharpCopyCacheChanged);
    UrmSharpCopyBoard.activeStateChanged
        .addListener(onUrmSharpCopyActiveStateChanged);
  }

  void _onMeasureRerenderReady(Object sender, void e) {
    update([
      activeCanvasLayerId,
      recordCanvasLayerId,
      annotationRecordCanvasLayerId,
      measureResultLayerId
    ]);
  }

  /// 画幅切换事件
  void _visualAreaChanged(sender, IVisualArea e) {
    onVisualAreaChanged.call(e.mode.modeType.toString().split('.')[1]);
  }

  IMeasureItem? currMeasureItem;

  /// 测量项状态切换事件
  void _onActiveMeasureItemChanged(_, IMeasureItem? e) {
    update([sharpCopySectionLayerId, sharpCopyToolLayerId]);

    if (e == null) return;
    if (currMeasureItem != null) {
      currMeasureItem!.onItemStatesChanged.removeListener(_onItemStatesChanged);
    }

    /// 组合测量项看成一个整体
    if (e is TopMeasureItem) {
      _enableAccessibility();
    }
    currMeasureItem = e;
    currMeasureItem!.onItemStatesChanged.addListener(_onItemStatesChanged);
  }

  void _onItemStatesChanged(_, ItemStates? e) {
    if (e == ItemStates.running) {
      _enableAccessibility();
    } else {
      // 此时可以认为是结束了一次测量
      _disableAccessibility();
      onMeasureFinishedOnce?.call(true);
    }
  }

  void _onCrossFrameTriggered(_, e) {
    final crossContext = CrossFrameContext(
      _imageUrl!,
      app!.frameData!,
      app!.activeMeasureItem!,
    );
    crossContext.imageCount = _imageCount;
    crossContext.probe = _probe;
    crossContext.measureAutoOver.addListener(_onCrossMeasureAutoOver);
    _crossFrameContext = crossContext;
    app!.crossFrameContext = crossContext;
    onCrossFramesTriggered.call(crossContext);
  }

  void _onCrossFrameAdded(_, int e) {
    if (!_crossFrameIndexList.contains(e)) {
      _crossFrameIndexList.add(e);
      onCrossFramesChanged.call(_crossFrameIndexList);
    }
  }

  void _onCrossMeasureAutoOver(_, e) {
    _crossFrameContext!.finish();
    onCrossFramesOver.call(_crossFrameContext!);

    if (_crossFrameContext!.originUrl != _crossFrameContext!.currentUrl) {
      // 跨图，需要通知外层切换图，延迟回复Application
    } else {
      // 跨帧
      _crossFrameIndexList.clear();
      onCrossFramesChanged.call(_crossFrameIndexList);
      _crossFrameContext = null;
    }
  }

  bool _checkAndHandleCrossImage() {
    _crossFrameIndexList.clear();
    if (_crossFrameContext == null) {
      return true;
    }
    if (_crossFrameContext!.isOver) {
      if (_crossFrameContext!.currentIndex == _crossFrameContext!.originIndex) {
        // 释放跨帧测量状态
        _crossFrameContext = null;
      } else {
        // 等待图像切换完成，再切回原始帧索引
      }
      return false;
    }
    final switchRst = _crossFrameContext!.switchImage(_imageUrl!);
    if (switchRst) {
      app!.updateRenderReady.emit(this, null);
      // 切换到指定图，恢复跨帧指示器记录
      _crossFrameIndexList.addAll(_crossFrameContext!.recordIndexList);
      return false;
    } else {
      // 超过跨图限制，结束之前的测量
      return true;
    }
  }

  // 撤销上次测量
  int undoMeasure() {
    int result = -1;
    if (app != null) {
      result = app!.undoRecord();
      listenTopMeasureItem(app!);
    }
    return result;
  }

  // 清空测量结果
  void clearMeasure() {
    if (app != null) {
      app!.clearRecords();
      listenTopMeasureItem(app!);
    }
  }

  // 清空或测量后重新监听组合测量项变化
  void listenTopMeasureItem(IApplication app) {
    final IMeasureItem? item = app.activeMeasureItem;
    if (item != null && item is ITopMeasureItem) {
      // 重新选中当前的组合测量项
      app.switchItem(item.meta);
      final IMeasureItem? newItem = app.activeMeasureItem;
      if (newItem != null && newItem is ITopMeasureItem) {
        newItem.switchChild(0);
        onWorkingChildChanged(0);
        newItem.workingChildChanged.addListener(_onWorkingChildChanged);
      }
    }
  }

  void onUrmSharpCopyCacheChanged(Object sender, e) {
    update([sharpCopySectionLayerId, sharpCopyToolLayerId]);
  }

  void onUrmSharpCopyActiveStateChanged(Object sender, e) {
    update([sharpCopySectionLayerId, sharpCopyToolLayerId]);
  }

  void applicationLoadFrame(VidUsImage? frame) {
    if (frame == null) {
      return;
    }
    if (_crossFrameContext != null && _crossFrameContext!.isOver) {
      _crossFrameContext = null;
      return;
    }
    final application = Get.find<IApplication>();
    application.loadFrame(frame);
    // FIXME 临时解决方案，实际应该使用播放状态来判断
    application.canMeasure = true;
    var visuals = application.visuals;
    if (visuals.isNotEmpty) {
      var firstVisual = visuals.first;
      if (firstVisual is V2dVisual) {
        VidUs2DVisual visualData = firstVisual.visualData;
        Map<VidUsVisualAreaType, VidUsLogicalCoordinate> logicalCoordinates =
            visualData.logicalCoordinates;
        if (logicalCoordinates.isNotEmpty &&
            logicalCoordinates.containsKey(VidUsVisualAreaType.Tissue)) {
          VidUsLogicalCoordinate logicalCoordinate =
              logicalCoordinates[VidUsVisualAreaType.Tissue]!;
          imageWidth =
              logicalCoordinate.region.right - logicalCoordinate.region.left;
          update([VidUIRepaintOverlayController.scaleBarId]);
        }
      }
    }
  }

  /// 切换到 URM 模式
  Future<void> buildURMMeasureApplication({
    required VidUsProbe probe,
    required int imageCount,
    required String url,
    required IURMDataProcessor dataProcessor,
    required ImageType imageType,
  }) async {
    this.imageType = imageType;
    _probe = probe;
    _imageUrl = url;
    _imageCount = imageCount;
    await LayoutConfiguration.ins.loadData();
    _initMouseModuel();
    if (app != null) {
      _disposeCurrentApp();
    }
    app = URMApplication(
      _probe!,
      urmDataProcessor: dataProcessor,
      resultWidth: 600, // 图像详情中取 分析结果的宽度
      resultHeight: 800, // 图像详情中取 分析结果的高度
      onUpdatePerfusion: onUpdatePerfusion,
      onUpdateChart: onUpdateChart,
      onUpdateRimResult: onUpdateRimResult,
    );
    Get.delete<IApplication>();
    Get.put<IApplication>(app!);
    app!.isSingleFrame = true;
    update([imageMeasureOverlayId]);
    app!.updateRenderReady.addListener(_onMeasureRerenderReady);
    app!.visualAreaChanged.addListener(_visualAreaChanged);
    app!.activeMeasureItemChanged.addListener(_onActiveMeasureItemChanged);
    _updateApplicationDisplaySizeOnly();
    // (app! as URMApplication).loadURMVisuals();

    UrmSharpCopyBoard.typeCacheChanged.addListener(onUrmSharpCopyCacheChanged);
    UrmSharpCopyBoard.activeStateChanged
        .addListener(onUrmSharpCopyActiveStateChanged);
  }

  /// 查找多区域
  void _findMultiRegions() {
    if (app == null) {
      return;
    }
    final application = app!;
    final displaySize = application.displaySize;
    ifContainerTissueTM = false;
    tissueTMPixelRegion = RectRegion();
    for (var visual in application.visuals) {
      for (var area in visual.visualAreas) {
        if (area.visualAreaType == VidUsVisualAreaType.TissueTimeMotion ||
            area.visualAreaType == VidUsVisualAreaType.Doppler) {
          ifContainerTissueTM = true;

          ///TODO 由于布局问题 Left 定位给不准，这里放宽到边界
          tissueTMPixelRegion = RectRegion.rect(DRect(
            // area.displayRegion.left * displaySize.width,
            0,
            area.displayRegion.top * displaySize.height,
            // area.displayRegion.width * displaySize.width,
            displaySize.width,
            area.displayRegion.height * displaySize.height,
          ));
        }
      }
    }
    update([mouseGestureLayerId]);
  }

  void _handleKeyEvent(RawKeyEvent event) {
    if (event is RawKeyDownEvent && event.data is RawKeyEventDataWeb) {
      final data = event.data as RawKeyEventDataWeb;
      switch (data.key) {
        case 'ArrowUp':
          rpc.platform.setCursorPosition(0, -1);
          break;
        case 'ArrowDown':
          rpc.platform.setCursorPosition(0, 1);
          break;
        case 'ArrowLeft':
          rpc.platform.setCursorPosition(-1, 0);
          break;
        case 'ArrowRight':
          rpc.platform.setCursorPosition(1, 0);
          break;
      }
    }
  }

  // 启用微调测量点功能
  void _enableAccessibility() {
    showAccessibility = true;
    update([accessibilityLayerId]);
    RawKeyboard.instance.addListener(_handleKeyEvent);
  }

  // 禁用微调测量点功能
  void _disableAccessibility() {
    showAccessibility = false;
    update([accessibilityLayerId]);
    RawKeyboard.instance.removeListener(_handleKeyEvent);
  }

  void onMouseDown(Offset position) {
    app?.createPointInfo(
      position,
      PointInfoType.mouseDown,
    );
  }

  void onMouseMove(Offset position) {
    mouseState?.mousePosition = position;
    app?.createPointInfo(
      position,
      PointInfoType.mouseMove,
    );
  }

  @override
  void onClose() {
    super.onClose();
  }

  void updateImageWidth(double maxWidth) {
    imageAreaWidth = maxWidth;
    print("set imageAreaWidth:$imageAreaWidth");
    Future.delayed(Duration(milliseconds: 200), () {
      update([VidUIRepaintOverlayController.scaleBarId]);
    });
  }
}
