import 'package:flutter/material.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/image_measure_overlay/controller.dart';
import 'package:flyinsono/lab/pages/lab_image/widgets/image_operate_panel/widgets/roi_copy_panel.dart';
import 'package:get/get.dart';
import 'package:fis_measure/interfaces/date_types/vector.dart';
import 'package:fis_measure/interfaces/date_types/point.dart';
import 'package:fis_measure/interfaces/process/workspace/application.dart';
import 'package:fis_measure/interfaces/process/workspace/point_info.dart';
import 'package:fis_measure/process/primitives/utils/urm_sharp_copy.dart';
import 'package:fis_measure/process/primitives/ellipse.dart';
import 'package:fis_measure/process/primitives/urm_measure/urm_rect_measure.dart';
import 'package:fis_measure/process/primitives/urm_measure/urm_trace_measure.dart';
import 'package:fis_measure/process/primitives/urm_measure/urm_ellipse_measure.dart';
import 'package:fis_measure/process/primitives/urm_measure/urm_shell_measure.dart';

class SharpCopySectionLayer extends GetView<ImageMeasureOverlayController> {
  SharpCopySectionLayer({
    super.key,
    required this.tabHashCode,
    this.isURMDualImages = false,
  });

  @override
  String? get tag => tabHashCode;

  final String tabHashCode;

  final bool isURMDualImages;

  @override
  Widget build(BuildContext context) {
    return GetBuilder<ImageMeasureOverlayController>(
      tag: tabHashCode,
      id: ImageMeasureOverlayController.sharpCopySectionLayerId,
      builder: (_) {
        if (controller.app == null) return const SizedBox();
        if (controller.app!.activeMeasureItem == null) return const SizedBox();
        if (UrmSharpCopyBoard.activeState == null) return const SizedBox();

        final state = UrmSharpCopyBoard.activeState!;
        final typeCache = UrmSharpCopyBoard.getCachedList(state.type);
        final data = typeCache[state.index];
        final dragController = DragController(
          sharpType: data.type,
          points: data.points,
          application: controller.app!,
        );
        return Stack(
          key: ValueKey(dragController),
          children: [
            Row(
              children: [
                if (isURMDualImages)
                  Expanded(
                    child: DragDrawLayer(
                      controller: dragController,
                      isURMDualImages: isURMDualImages,
                    ),
                  ),
                Expanded(
                  child: DragDrawLayer(
                    controller: dragController,
                    isURMDualImages: isURMDualImages,
                  ),
                ),
              ],
            ),
            Row(
              children: [
                if (isURMDualImages)
                  Expanded(
                    child: DragGestureLayer(controller: dragController),
                  ),
                Expanded(
                  child: DragGestureLayer(controller: dragController),
                ),
              ],
            ),
          ],
        );
      },
    );
  }
}

class DragController extends ChangeNotifier {
  final List<DPoint> points;
  final UrmSharpCopyDataType sharpType;
  final IApplication application;

  DPoint centerPoint = DPoint.zero;
  DVector? vector;

  DragController({
    required this.points,
    required this.sharpType,
    required this.application,
  }) {
    centerPoint = _calcCenterPoint(points);
  }

  void updatePosition(Offset offset, {required Size size}) {
    final x = offset.dx / size.width;
    final y = offset.dy / size.height;
    final p = DPoint(x, y);
    centerPoint = _calcCenterPoint(points);
    vector = p - centerPoint;
    notifyListeners();
  }

  void confirmPosition() {
    print(vector);
    final item = application.activeMeasureItem!;
    if (item.feature != null) {
      item.cancelOnce();
    }
    final sectionPoints =
        points.map((e) => e.clone().addVector(vector!)).toList();
    final firstPointInfo = PointInfo(
      sectionPoints.first.x,
      sectionPoints.first.y,
      PointInfoType.mouseDown,
    );
    firstPointInfo.hostVisualArea = application.currentVisualArea;
    if (item is URMRectMeasure) {
      item.handleMouseDownWhileWaiting(firstPointInfo);
      item.feature!.endPoint = sectionPoints[1];
      item.handleFinish(recordSharp: false);
    } else if (item is URMEllipseMeasure) {
      item.handleMouseDownWhileWaiting(firstPointInfo);
      final f = item.feature! as EllipseFeature;
      f.activeIndex = 1;
      for (var i = 1; i < sectionPoints.length; i++) {
        f.innerPoints[i] = sectionPoints[i];
      }
      f.activeIndex = 2;
      item.handleFinish(recordSharp: false);
    } else if (item is URMTraceMeasure) {
      item.handleMouseDownWhileWaiting(firstPointInfo);
      for (var i = 1; i < sectionPoints.length; i++) {
        item.feature!.adopt(sectionPoints[i]);
      }
      item.handleFinish(recordSharp: false);
    } else if (item is URMShellMeasure) {
      item.handleMouseDownWhileWaiting(firstPointInfo);
      for (var i = 1; i < sectionPoints.length; i++) {
        item.feature!.adopt(sectionPoints[i]);
      }
      item.handleFinish(recordSharp: false);
    }
  }

  DPoint _calcCenterPoint(List<DPoint> points) {
    if (points.isEmpty) {
      return DPoint.zero; // 如果数组为空，返回原点作为默认值
    }

    double totalX = 0.0;
    double totalY = 0.0;

    // 累加所有点的x和y坐标
    for (DPoint point in points) {
      totalX += point.x;
      totalY += point.y;
    }

    // 计算平均x和y坐标
    double centerX = totalX / points.length;
    double centerY = totalY / points.length;

    // 创建并返回中心点
    return DPoint(centerX, centerY);
  }
}

class DragGestureLayer extends StatelessWidget {
  final DragController controller;

  const DragGestureLayer({super.key, required this.controller});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, c) {
      final size = Size(c.maxWidth, c.maxHeight);
      return MouseRegion(
        cursor: SystemMouseCursors.cell,
        onHover: (event) {
          controller.updatePosition(event.localPosition, size: size);
        },
        child: GestureDetector(
          onTap: () {
            controller.confirmPosition();
          },
        ),
      );
    });
  }
}

class DragDrawLayer extends StatefulWidget {
  final DragController controller;
  final bool isURMDualImages;

  const DragDrawLayer({
    super.key,
    required this.controller,
    required this.isURMDualImages,
  });

  @override
  State<StatefulWidget> createState() => _DragDrawLayerState();
}

class _DragDrawLayerState extends State<DragDrawLayer> {
  late final DragController controller;
  DPoint? position;
  DVector? vector;

  @override
  void initState() {
    controller = widget.controller;
    controller.addListener(_onPositionUpdate);
    super.initState();
  }

  @override
  void dispose() {
    controller.removeListener(_onPositionUpdate);
    super.dispose();
  }

  void _onPositionUpdate() {
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (_, c) {
      final vector = controller.vector;
      if (vector == null) {
        return const SizedBox();
      }
      // final points = controller.points;
      final points =
          controller.points.map((e) => e.clone().addVector(vector)).toList();
      final size = Size(c.maxWidth, c.maxHeight);
      return CustomPaint(
        size: size,
        // painter: _DragDrawPainter(
        //   points,
        //   vector: vector,
        //   sharpType: controller.sharpType,
        // ),
        painter: ShapeCopyPainter(
          UrmSharpCopyData.create(controller.sharpType, points),
          isURMDualImages: widget.isURMDualImages,
        ),
      );
    });
  }
}

class _DragDrawPainter extends CustomPainter {
  static final paintPen = Paint()
    ..color = Colors.red
    ..isAntiAlias = true
    ..strokeWidth = 2
    ..style = PaintingStyle.stroke;

  final List<DPoint> points;
  final DVector vector;
  final UrmSharpCopyDataType sharpType;

  _DragDrawPainter(
    this.points, {
    required this.vector,
    required this.sharpType,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final offsets = points
        .map((e) => e.clone().addVector(vector).scale2Size(size).toOffset())
        .toList();

    final startOffset = offsets[0];
    final endOffset = offsets[1];
    canvas.drawRect(Rect.fromPoints(startOffset, endOffset), paintPen);
  }

  @override
  bool shouldRepaint(covariant _DragDrawPainter oldDelegate) {
    return oldDelegate.vector != vector;
  }
}
