import 'dart:convert';
import 'dart:ui';

import 'package:fis_measure/interfaces/date_types/point.dart';
import 'package:fis_measure/process/primitives/carotid_imt.dart';
import 'package:fis_measure/utils/js_utils.dart'
    if (dart.library.io) 'package:fis_measure/utils/js_utils4native.dart'
    if (dart.library.html) 'package:fis_measure/utils/js_utils.dart';
import 'package:vid/us/vid_us_unit.dart';

import 'calculator.dart';

class CarotidCal extends Calculator<CarotidIMT, double> {
  CarotidCal(CarotidIMT ref, this.type) : super(ref);
  String type = '';
  @override
  void calculate() {
    if (ref.feature == null) return;
    final p1 = ref.feature!.startPoint;
    final p2 = ref.feature!.endPoint;
    //左上顶点
    final leftTopPoint =
        DPoint(p1.x < p2.x ? p1.x : p2.x, p1.y < p2.y ? p1.y : p2.y);
    //右下顶点
    final rightBottomPoint =
        DPoint(p1.x > p2.x ? p1.x : p2.x, p1.y > p2.y ? p1.y : p2.y);
    //图片尺寸
    final imageSize = ref.application.carotid2DSize;
    //画布尺寸
    final canavsSize = ref.application.displaySize;
    //图像缩放比
    final imageScale = ref.application.displayScaleRatio;
    //标准画布尺寸
    final stdCanavsSize =
        Size(canavsSize.width / imageScale, canavsSize.height / imageScale);
    //Vid图像左上顶点的像素坐标
    final imageLeftTopPoint = DPoint(
        (stdCanavsSize.width - imageSize.width) / 2,
        (stdCanavsSize.height - imageSize.height) / 2);
    //Vid图像右下顶点的像素坐标
    final imageRightBottomPoint = DPoint(imageLeftTopPoint.x + imageSize.width,
        imageLeftTopPoint.y + imageSize.height);
    //选区左上顶点的像素坐标
    final rectLeftTopPoint = DPoint(stdCanavsSize.width * leftTopPoint.x,
        stdCanavsSize.height * leftTopPoint.y);
    //选区右下顶点的像素坐标
    final rectRightBottomPoint = DPoint(
        stdCanavsSize.width * rightBottomPoint.x,
        stdCanavsSize.height * rightBottomPoint.y);

    /// 在图像外的点改到图像边缘上
    if (rectLeftTopPoint.x < imageLeftTopPoint.x) {
      rectLeftTopPoint.x = imageLeftTopPoint.x;
    }
    if (rectLeftTopPoint.x > imageRightBottomPoint.x) {
      rectLeftTopPoint.x = imageRightBottomPoint.x;
    }
    if (rectLeftTopPoint.y < imageLeftTopPoint.y) {
      rectLeftTopPoint.y = imageLeftTopPoint.y;
    }
    if (rectLeftTopPoint.y > imageRightBottomPoint.y) {
      rectLeftTopPoint.y = imageRightBottomPoint.y;
    }
    if (rectRightBottomPoint.x > imageRightBottomPoint.x) {
      rectRightBottomPoint.x = imageRightBottomPoint.x;
    }
    if (rectRightBottomPoint.x < imageLeftTopPoint.x) {
      rectRightBottomPoint.x = imageLeftTopPoint.x;
    }
    if (rectRightBottomPoint.y > imageRightBottomPoint.y) {
      rectRightBottomPoint.y = imageRightBottomPoint.y;
    }
    if (rectRightBottomPoint.y < imageLeftTopPoint.y) {
      rectRightBottomPoint.y = imageLeftTopPoint.y;
    }

    final rectLeft = (rectLeftTopPoint.x - imageLeftTopPoint.x).round();
    final rectTop = (rectLeftTopPoint.y - imageLeftTopPoint.y).round();
    final rectWidth = (rectRightBottomPoint.x - rectLeftTopPoint.x).round();
    final rectHeight = (rectRightBottomPoint.y - rectLeftTopPoint.y).round();
    String measureItemType = 'AntMeasureItem';
    if (type == 'Ant.CCA IMT') {
      measureItemType = 'AntMeasureItem';
    } else if (type == 'Post.CCA IMT') {
      measureItemType = 'PostMeasureItem';
    } else if (type == 'Both.CCA IMT') {
      measureItemType = 'AntAndPostMeasureItem';
    }
    final params =
        "{'MeasureItemType':'$measureItemType','IntimaRect':{'Left':$rectLeft,'Top':$rectTop,'Width':$rectWidth,'Height':$rectHeight}}";

    String description = "IMT\n Measuring";
    updateStringValue(description);
    List<Offset> getPointsFromStrList(List pointsStr) {
      final points = <Offset>[];
      for (var point in pointsStr) {
        final xyStr = point.split(',');
        points.add(Offset((double.parse(xyStr[0]) + imageLeftTopPoint.x),
            (double.parse(xyStr[1]) + imageLeftTopPoint.y)));
      }
      return points;
    }

    /// [Carotid] ✅在此处通知 Shell 计算,获取 description,touch/mouse finished 时绘制结果
    try {
      callShellMethod('getMeasureResult', [params]).callMethod(
        'then',
        [
          (result) {
            final feature = ref.feature!;
            // print("getMeasureResult: $result");
            if (result == 'error') {
              description = "\n Measure failed";
              updateStringValue(description);
              ref.application.updateRenderReady.emit(this, null);
              return;
            }

            final res = jsonDecode(result);
            if (res['ErrorCode'].toString() == "1000") {
              if (type != 'Both.CCA IMT') {
                description =
                    "\n Max: ${res['MaxThickness'].toStringAsFixed(2)}mm\n Min: ${res['MinThickness'].toStringAsFixed(2)}mm\n Avg: ${res['AverageThickness'].toStringAsFixed(2)}mm\n SD: ${res['SdThickness'].toStringAsFixed(2)}mm";
              } else {
                description =
                    "\n Ant Max: ${res['LowerMeasureResult']['MaxThickness'].toStringAsFixed(2)}mm\n Ant.Min: ${res['LowerMeasureResult']['MinThickness'].toStringAsFixed(2)}mm\n Ant.Avg: ${res['LowerMeasureResult']['AverageThickness'].toStringAsFixed(2)}mm\n Ant.SD: ${res['LowerMeasureResult']['SdThickness'].toStringAsFixed(2)}mm\n Post.Max: ${res['UpperMeasureResult']['MaxThickness'].toStringAsFixed(2)}mm\n Post.Min: ${res['UpperMeasureResult']['MinThickness'].toStringAsFixed(2)}mm\n Post.Avg: ${res['UpperMeasureResult']['AverageThickness'].toStringAsFixed(2)}mm\n Post.SD: ${res['UpperMeasureResult']['SdThickness'].toStringAsFixed(2)}mm";
              }
              if (type != 'Both.CCA IMT') {
                feature.offsetsList
                    .add(getPointsFromStrList(res['PointLower']));
                feature.offsetsList
                    .add(getPointsFromStrList(res['PointUpper']));
              } else {
                feature.offsetsList.add(getPointsFromStrList(
                    res['LowerMeasureResult']['PointLower']));
                feature.offsetsList.add(getPointsFromStrList(
                    res['LowerMeasureResult']['PointUpper']));
                feature.offsetsList.add(getPointsFromStrList(
                    res['UpperMeasureResult']['PointLower']));
                feature.offsetsList.add(getPointsFromStrList(
                    res['UpperMeasureResult']['PointUpper']));
              }
            } else {
              description = "\n Measure failed";
            }
            updateStringValue(description);

            /// [Carotid] ✅在此处通知canvas 重绘结果

            ref.application.updateRenderReady.emit(this, null);
          },
        ],
      );
    } catch (e) {
      updateStringValue("\n Measure failed");
      //
    }
  }
}