import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flyinsono/lab/pages/lab_image/urm_data_processor/index.dart';
import 'package:get/get.dart';
import 'dart:ui' as ui;
import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart' hide Image, decodeImageFromList;

class ImageRoiOverlayController extends GetxController {
  ImageRoiOverlayController({this.onRoiSelected, this.setRoiPercentOffset});

  VoidCallback? onRoiSelected;
  void Function(Offset, String)? setRoiPercentOffset;

  static const String imageRoiOverlayId = "image_roi_overlay";
  static const String imageRoiCanavsId = "image_roi_canvas";

  bool isActive = false; // 是否激活

  void active() {
    if (isActive) return;
    isActive = true;
    update([imageRoiOverlayId]);
    WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
      onRenderSizeChanged();
    });
  }

  void deactive() {
    if (!isActive) return;
    isActive = false;
    update([imageRoiOverlayId]);
  }

  bool showURMImage = false;
  RoiSelectStatus roiSelectStatus = RoiSelectStatus.wating; // ROI 选择状态
  Point<double>? roiStartPointRelativeToImage; // ROI 起始点
  Point<double>? roiEndPointRelativeToImage; // ROI 终止点

  // 当前的 URM 图像数据
  URMDataProcessor _urmDataProcessor = URMDataProcessor();
  // URMDataProcessor get urmDataProcessor => _urmDataProcessor;

  // 视图参数
  RoiViewType get roiViewType => _urmDataProcessor.visualInfo.roiViewType;
  double get beamsLeft => _urmDataProcessor.visualInfo.beamsLeftBoundary;
  double get beamsRight => _urmDataProcessor.visualInfo.beamsRightBoundary;
  double get beamsRangePercent => beamsRight - beamsLeft;
  bool get isLinear => _urmDataProcessor.visualInfo.isLinear;
  double get scanWidth => _urmDataProcessor.visualInfo.scanWidth;
  Offset get zeroCenterOffset => _urmDataProcessor.visualInfo.zeroCenterOffset;

  /// 从左侧开始框选（用于双幅的情况）
  bool startFromLeft = true;

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

  /// ROI 面板的渲染尺寸
  Size? roiLayerSize;

  /// ROI 面板的 key
  final GlobalKey imageRoiLayerKey = GlobalKey();

  /// 获取 ROI 在画布上的位置
  RoiPosRelativeToImage? getRoiRelativePos() {
    if (roiSelectStatus != RoiSelectStatus.selected) {
      return null;
    }
    if (roiStartPointRelativeToImage == null ||
        roiEndPointRelativeToImage == null) {
      return null;
    }
    return RoiPosRelativeToImage(
      x: roiStartPointRelativeToImage!.x,
      y: roiStartPointRelativeToImage!.y,
      width: (roiEndPointRelativeToImage!.x - roiStartPointRelativeToImage!.x)
          .abs(),
      height: (roiEndPointRelativeToImage!.y - roiStartPointRelativeToImage!.y)
          .abs(),
    );
  }

  /// 设置 ROI 位置，并显示
  void drawRoi(RoiPosRelativeToImage? roiPos) {
    if (roiPos == null) {
      roiSelectStatus = RoiSelectStatus.wating;
      roiStartPointRelativeToImage = null;
      roiEndPointRelativeToImage = null;
      update([imageRoiCanavsId]);
      return;
    }
    roiSelectStatus = RoiSelectStatus.selected;
    roiStartPointRelativeToImage = Point(roiPos.x, roiPos.y);
    roiEndPointRelativeToImage =
        Point(roiPos.x + roiPos.width, roiPos.y + roiPos.height);
    update([imageRoiCanavsId]);
  }

  /// 获取 ROI 结果
  RoiResult? getRoiResult() {
    if (roiSelectStatus != RoiSelectStatus.selected) {
      return null;
    }
    if (roiStartPointRelativeToImage == null ||
        roiEndPointRelativeToImage == null) {
      return null;
    }
    // 取最小的x和y作为起点
    final x =
        min(roiStartPointRelativeToImage!.x, roiEndPointRelativeToImage!.x);
    final y =
        min(roiStartPointRelativeToImage!.y, roiEndPointRelativeToImage!.y);
    final width =
        (roiEndPointRelativeToImage!.x - roiStartPointRelativeToImage!.x).abs();
    final height =
        (roiEndPointRelativeToImage!.y - roiStartPointRelativeToImage!.y).abs();
    NormCoord normCoordInVisualArea = _urmDataProcessor.calculator
        .calNormCoordInRegionByRoiPos(RoiPosRelativeToImage(
      x: x,
      y: y,
      width: width,
      height: height,
    ));
    print(normCoordInVisualArea);
    NormCoord fixedCoord = normCoordInVisualArea.getFixedNormCoord();
    _urmDataProcessor.calROIParam(fixedCoord);
    return _urmDataProcessor.getRoiResult();
  }

  /// 设置 URM 数据处理器
  void setURMDataProcessor(URMDataProcessor urmDataProcessor) {
    _urmDataProcessor = urmDataProcessor;
    update([imageRoiCanavsId]);
  }

  // 计算实际render的尺寸，赋值给 roiLayerSize
  void onRenderSizeChanged() {
    if (imageRoiLayerKey.currentContext == null) return;
    final RenderBox renderBox =
        imageRoiLayerKey.currentContext!.findRenderObject() as RenderBox;
    final size = renderBox.size;
    roiLayerSize = size;
  }

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

  void onMouseDown(Offset position) {
    print("roiSelectStatus:${roiSelectStatus.name}");
    switch (roiSelectStatus) {
      case RoiSelectStatus.wating:
        startFromLeft = isOnLeft(position);
        if (!isInValideArea(offsetToPoint(position))) {
          return;
        }
        roiSelectStatus = RoiSelectStatus.selecting;
        roiStartPointRelativeToImage = offsetToPoint(position);
        roiEndPointRelativeToImage = null;
        break;
      case RoiSelectStatus.selecting:
        roiSelectStatus = RoiSelectStatus.selected;
        final percentOffset = correctPosition(position);
        setRoiPercentOffset?.call(percentOffset, _urmDataProcessor.imageCode);
        final Point<double> percentPoint = offsetToPoint(percentOffset);
        roiEndPointRelativeToImage = correctBeamsBoundry(percentPoint);
        onRoiSelected?.call();
        break;
      case RoiSelectStatus.selected:
        startFromLeft = isOnLeft(position);
        if (!isInValideArea(offsetToPoint(position))) {
          return;
        }
        roiSelectStatus = RoiSelectStatus.selecting;
        roiStartPointRelativeToImage = offsetToPoint(position);
        roiEndPointRelativeToImage = null;
        break;
    }
    update([imageRoiCanavsId]);
  }

  // TODO 优化方案：ROI 过小时忽略
  void onMouseMove(Offset position) {
    if (roiSelectStatus == RoiSelectStatus.selecting) {
      final percentOffset = correctPosition(position);
      final Point<double> percentPoint = offsetToPoint(percentOffset);
      roiEndPointRelativeToImage = correctBeamsBoundry(percentPoint);
      update([imageRoiCanavsId]);
    }
  }

  Point<double> offsetToPoint(Offset position) {
    if (roiLayerSize == null ||
        roiLayerSize!.width == 0 ||
        roiLayerSize!.height == 0) {
      return Point(0, 0);
    }
    final double x = position.dx / roiLayerSize!.width;
    final double y = position.dy / roiLayerSize!.height;
    if (roiViewType == RoiViewType.leftRightHalfHalf) {
      if (startFromLeft) {
        return Point(x * 2, y);
      } else {
        if (x * 2 > 2) {
          return Point(x * 2 - 1, y);
        }
        return Point(x * 2 % 1, y);
      }
    }
    return Point(x, y);
  }

  // 矫正位置保持在同一侧
  Offset correctPosition(Offset position) {
    if (roiLayerSize == null ||
        roiLayerSize!.width == 0 ||
        roiLayerSize!.height == 0) {
      return position;
    }
    if (!isLinear) {
      if (position.dx >= roiLayerSize!.width - 5) {
        var aDegrees = _urmDataProcessor.visualInfo.scanWidth / 2;
        var zeroCenterOffset = _urmDataProcessor.visualInfo.zeroCenterOffset;
        double topHeight = zeroCenterOffset.dy.abs() * roiLayerSize!.height;
        double aRadians = aDegrees * (pi / 180);
        double x = (position.dy + topHeight) * tan(aRadians) +
            roiLayerSize!.width * 3 / 4;
        return Offset(x, position.dy);
      }
      return position;
    }
    final double horizontalCenetr = roiLayerSize!.width / 2;
    if (roiViewType == RoiViewType.leftRightHalfHalf) {
      if (startFromLeft) {
        return Offset(
          min(position.dx, horizontalCenetr),
          position.dy,
        );
      } else {
        return Offset(
          max(position.dx, horizontalCenetr),
          position.dy,
        );
      }
    }
    return position;
  }

  // 矫正边界
  Point<double> correctBeamsBoundry(Point<double> point) {
    if (!isLinear) {
      return point;
    }
    if (point.x < beamsLeft) {
      return Point(beamsLeft, point.y);
    }
    if (point.x > beamsRight) {
      return Point(beamsRight, point.y);
    }
    return point;
  }

  bool isOnLeft(Offset position) {
    if (roiLayerSize == null ||
        roiLayerSize!.width == 0 ||
        roiLayerSize!.height == 0) {
      return false;
    }
    final double x = position.dx / roiLayerSize!.width;
    print("startFromLeft: ${x < 0.5}");
    return x < 0.5;
  }

  // 是否在有效区域
  bool isInValideArea(Point<double> point) {
    double x = point.x;
    return x > beamsLeft && x < beamsRight;
  }

  Future<ui.Image?> generateUrmImage(Uint8List bytes) async {
    try {
      final buffer = await ui.ImmutableBuffer.fromUint8List(bytes);
      final descriptor = await ui.ImageDescriptor.encoded(buffer);
      final codec = await descriptor.instantiateCodec();
      final frameInfo = await codec.getNextFrame();
      codec.dispose();
      return frameInfo.image;
    } catch (e) {
      print("decode image error: $e");
      return null;
    }
  }

  // @override
  // void onInit() {
  //   super.onInit();
  // }

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

enum RoiSelectStatus {
  wating, // 未开始
  selecting, // 选择中
  selected, // 已选择
}

enum TraceStatus {
  wating, // 未开始
  selecting, // 选择中
  end, // 已选择
}
