import 'package:fis_jsonrpc/rpc.dart';
import 'package:fis_measure/interfaces/date_types/point.dart';
import 'package:fis_measure/interfaces/enums/items.dart';
import 'package:fis_measure/interfaces/process/items/item.dart';
import 'package:fis_measure/interfaces/process/items/item_metas.dart';
import 'package:fis_measure/interfaces/process/items/types.dart';
import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_den_measure.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_den_vel_measure.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_density.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_fractal_dim.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_hist.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_perfusion.dart';
import 'package:fis_measure/process/calcuators/urm_calcuators/urm_ellipse_vel_measure.dart';
import 'package:fis_measure/process/primitives/ellipse.dart';
import 'package:fis_measure/process/primitives/utils/urm_sharp_copy.dart';
import 'package:fis_measure/utils/prompt_box.dart';
import 'package:flutter/material.dart';
import 'dart:ui' as ui;

class URMEllipseMeasure extends Ellipse {
  URMEllipseMeasure(super.meta, super.parent);

  static URMEllipseMeasure createURMEllipseDenMeasure(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipse = URMEllipseMeasure(meta, parent);
    measureEllipse.calculator = URMEllipseDenMeasureCal(
      measureEllipse,
    );
    return measureEllipse;
  }

  static URMEllipseMeasure createURMEllipseHist(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureHist = URMEllipseMeasure(meta, parent);
    measureHist.calculator = URMEllipseHistCal(
      measureHist,
    );
    return measureHist;
  }

  static URMEllipseMeasure createURMEllipseDenVelMeasure(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipseDenVel = URMEllipseMeasure(meta, parent);
    measureEllipseDenVel.calculator = URMEllipseDenVelMeasureCal(
      measureEllipseDenVel,
    );
    return measureEllipseDenVel;
  }

  static URMEllipseMeasure createURMEllipseDensity(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipseDensity = URMEllipseMeasure(meta, parent);
    measureEllipseDensity.calculator = URMEllipseDensityCal(
      measureEllipseDensity,
    );
    return measureEllipseDensity;
  }

  static URMEllipseMeasure createURMEllipseFractalDim(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipseFractalDim =
        URMEllipseMeasure(meta, parent);
    measureEllipseFractalDim.calculator = URMEllipseFractalDimCal(
      measureEllipseFractalDim,
    );
    return measureEllipseFractalDim;
  }

  static URMEllipseMeasure createURMEllipseVelMeasure(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipseVel = URMEllipseMeasure(meta, parent);
    measureEllipseVel.calculator = URMEllipseVelMeasureCal(
      measureEllipseVel,
    );

    return measureEllipseVel;
  }

  static URMEllipseMeasure createURMEllipsePerfusion(ItemMeta meta,
      [IMeasureItem? parent]) {
    URMEllipseMeasure measureEllipsePerfusion = URMEllipseMeasure(meta, parent);
    measureEllipsePerfusion.calculator = URMEllipsePerfusionCal(
      measureEllipsePerfusion,
    );
    return measureEllipsePerfusion;
  }

  @override
  bool onExecuteMouse(PointInfo args) {
    if (state == ItemStates.finished) {
      if (args.pointType == PointInfoType.mouseDown) {
        state = ItemStates.waiting;
      }
    }

    if (state == ItemStates.waiting) {
      if (args.pointType == PointInfoType.mouseDown) {
        handleMouseDownWhileWaiting(args);
      }
    } else if (state == ItemStates.running) {
      if (feature == null) return false;
      final f = feature! as EllipseFeature;
      final activeIndex = f.activeIndex;

      switch (args.pointType) {
        case PointInfoType.mouseMove:
          f.innerPoints[activeIndex] = args;
          f.adjustPoints(args);
          break;
        case PointInfoType.mouseDown:
          if (activeIndex == 1) {
            if (f.xAxisEnd == f.xAxisStart) {
              break;
            }
            f.adjustPoints(args);
            f.activeIndex = 2;
          } else if (activeIndex == 2) {
            handleFinish();
          }
          break;
        default:
          return false;
      }

      doCalculate();
      // handleFinish();
      return true;
    }
    return false;
  }

  @override
  void handleMouseDownWhileWaiting(PointInfo args) {
    if (meta.measureType == MeasureTypes.URMEllipsePerfusion) {
      final point = args.toAreaLogicPoint();
      feature = EllipsePerfusionImageFeature(this, point);
      if (args.hostVisualArea != null) {
        feature!.hostVisualArea = args.hostVisualArea;
      }
      feature!.activeIndex = 1;
    } else {
      super.handleMouseDownWhileWaiting(args);
    }
    state = ItemStates.running;
  }

  bool waitingResult = false;

  void handleFinish({bool recordSharp = true}) async {
    if (recordSharp) {
      _recordSharp();
    }

    feature!.isActive = false;
    waitingResult = true;
    await doCalculateAsync();
    doFeatureFinish();
    doFeatureUpdate(); // 若不执行,子测量将无法自动切换
    PromptBox.dismiss();
    waitingResult = false;
    doFeatureFinish();
  }

  void _recordSharp() {
    UrmSharpCopyBoard.recordSharp(
      UrmSharpCopyDataType.ellipse,
      feature!.innerPoints,
    );
  }
}

class EllipsePerfusionImageFeature extends EllipseFeature {
  EllipsePerfusionImageFeature(Ellipse refItem, DPoint point)
      : super(refItem, point);

  ui.Image? perfusionImg;
  IntRect? perfusionPiexlRect;
  DPoint? leftTopPoint;
  DPoint? rightBottomPoint;

  /// 绘制灌注图
  @override
  void paintPerfusion(Canvas canvas, Size size) {
    if (perfusionImg != null) {
      Paint paint = Paint();

      Rect src = Rect.fromLTWH(
        0,
        0,
        perfusionImg!.width.toDouble(),
        perfusionImg!.height.toDouble(),
      );
      if (leftTopPoint == null || rightBottomPoint == null) {
        return;
      }
      DPoint leftTop = convert2ViewPoint(size, leftTopPoint!);
      DPoint rightBottom = convert2ViewPoint(size, rightBottomPoint!);
      convert2ViewPoint(size, rightBottomPoint!);
      Rect dst = Rect.fromPoints(
          Offset(leftTop.x, leftTop.y), Offset(rightBottom.x, rightBottom.y));

      canvas.drawImageRect(perfusionImg!, src, dst, paint);
    }
  }
}