// 试卷绘制
import 'dart:io';
import 'dart:ui' as ui;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/common/model/job/gesture_recording.dart';
import 'package:marking_app/common/model/marking/annotation_graffiti_switch.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/homework_correction/components/jobPictureOverview.dart';
import 'package:marking_app/provider/annotation_graffiti_switch_provider.dart';
import 'package:marking_app/utils/index.dart';

// 试卷绘制
class ExamPaperDrawing extends StatefulHookConsumerWidget {
  String imgUrl;
  bool homework;
  BoxDecoration? decoration;
  AnnotationGraffitiSwitch graffitiSwitch;
  List<GestureRecording>? points;
  List<dynamic>? pointsPureData;
  ValueNotifier<Map<String, ui.Image>> imageLoaded;

  GlobalKey globalKey;
  // Function(String) imageCall;
  ExamPaperDrawing({
    required this.imgUrl,
    required this.homework,
    required this.points,
    required this.pointsPureData,
    required this.graffitiSwitch,
    required this.globalKey,
    required this.imageLoaded,
    this.decoration,
    Key? key,
  }) : super(key: key);

  @override
  _ExamPaperDrawingState createState() => _ExamPaperDrawingState();
}

class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing>
    with EventBusMixin<BottomAnnotationSwitchCleanall> {
  late Future<ui.Image?> _future; // 考试试卷

  // 用于记录手指位置的变量
  late List<GestureRecording> points;
  late List<dynamic> pointsPureData;
  // 用于记录绘图结果的变量
  bool _isEraserPressed = false; // 橡皮擦按下
  Offset? _eraserPosition; // 按下位置
  Offset? globalPosition = null; // 是否正在绘制

  Future<ui.Image?> loadImage(String url) async {
    try {
      Map<String, ui.Image> map = widget.imageLoaded.value;
      ui.Image? image = map[url];
      if (image != null) {
        return image;
      }
      final httpClient = HttpClient();
      final request = await httpClient.getUrl(Uri.parse(url));
      final response = await request.close();
      final bytes = await consolidateHttpClientResponseBytes(response);
      final codec = await ui.instantiateImageCodec(bytes);
      final frame = await codec.getNextFrame();
      ui.Image theImage = frame.image;
      map[url] = theImage;
      return theImage;
    } catch (e) {
      print('请求图片报错：${e.toString()}');
    }
    return null;
  }

  // void _onPointerDown(DragDownDetails details) {
  //   if (widget.graffitiSwitch.openEraser) {
  //     _eraserPosition = (context.findRenderObject() as RenderBox).globalToLocal(details.globalPosition);
  //     _isEraserPressed = true;
  //     toUpState(setState, ()=>{}, mounted);
  //   }
  // }

  @override
  void initState() {
    points = widget.points ?? [];
    pointsPureData = widget.pointsPureData ?? [];
    print('图片地址：${widget.imgUrl}');
    _future = loadImage(widget.imgUrl);
    // 事件总线监听
    eventOn(callback: (BottomAnnotationSwitchCleanall item) {
      if (item.previousStep) {
        if (points.isEmpty) {
          ToastUtils.showInfo('批注已清空');
          return;
        }
        var index = pointsPureData.toList().lastIndexOf(null);
        if (index != -1) {
          if (index + 1 == pointsPureData.length) {
            pointsPureData = pointsPureData.sublist(0, index);
            points.sublist(0, index);
            index = pointsPureData.toList().lastIndexOf(null);
            index == -1 ? -1 : index + 1;
          }
          if (index != -1) {
            pointsPureData = pointsPureData.sublist(0, index);
            points = points.sublist(0, index);
            toUpState(setState, () {}, mounted);
          } else {
            item.cleanAll = true;
          }
        } else {
          item.cleanAll = true;
        }
      }

      if (item.cleanAll) {
        pointsPureData.clear();
        points.clear();
        toUpState(setState, () {}, mounted);
      }

      if (item.uploadImage) {
        // 图片确认按钮，生成
        if (pointsPureData.isEmpty) {
          ToastUtils.showInfo('请先批注再提交');
          return;
        }
        // _saveImage().then((FileResult? res) {
        //   if (res != null) {
        //     widget.imageCall(res.url!);
        //   }
        // });
      }
    });
    super.initState();
  }

  @override
  void dispose() {
    super.dispose();
    eventCancel();
  }

  @override
  Widget build(BuildContext context) {
    return MyFutureBuilder.buildFutureBuilderOfSingleInstance<ui.Image>(
      context,
      _future,
      (ui.Image? theImage) {
        if (theImage == null) return const Center(child: Text('图片加载错误'));

        return LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
            final double containerWidth = constraints.maxWidth; // 展示区域总宽度
            final double containerHeight = constraints.maxHeight; // 展示区域总宽度

            final double imageWidth = theImage.width.toDouble(); // 图片原始宽度
            final double imageHeight = theImage.height.toDouble(); // 图片原始高度
            final double widthRatio = containerWidth / imageWidth; //
            final double heightRatio = containerHeight / imageHeight;
            final double scale = widthRatio > heightRatio ? heightRatio : widthRatio;
            final double destWidth = imageWidth * scale;
            final double destHeight = imageHeight * scale;

            final bool homework = widget.homework;

            return GestureDetector(
              behavior: HitTestBehavior.opaque,
              onPanUpdate: (DragUpdateDetails details) {
                if (globalPosition != null) {
                  // 预防双指同时作用于屏幕
                  double dx = globalPosition!.dx;
                  double dy = globalPosition!.dy;

                  double dxNew = details.globalPosition.dx;
                  double dyNew = details.globalPosition.dy;
                  if ((dxNew - dx).abs() > 22 || (dyNew - dy).abs() > 22) {
                    return;
                  }
                }
                globalPosition = details.globalPosition;
                try {
                  if (widget.graffitiSwitch.openBrush || widget.graffitiSwitch.openEraser) {
                    RenderBox renderBox = context.findRenderObject() as RenderBox;
                    Offset localPosition = renderBox.globalToLocal(details.globalPosition);
                    pointsPureData = List.from(pointsPureData)..add(localPosition);
                    bool annotationSwitch = ref.read(annotationGraffitiSwitchProvider).annotationSwitch; // 底部开关是否打开
                    points = List.from(points)
                      ..add(GestureRecording(
                          eraser: widget.graffitiSwitch.openEraser,
                          data: localPosition,
                          annotationSwitch: annotationSwitch));
                    _eraserPosition = localPosition;
                    _isEraserPressed = true;
                    setState(() {});
                  }
                } catch (e) {
                  toPrint(val: '进入报错');
                }
              },
              onPanEnd: (DragEndDetails details) {
                print('离开.............');
                globalPosition = null;
                if (widget.graffitiSwitch.openBrush || widget.graffitiSwitch.openEraser) {
                  pointsPureData.add(null); // 增加空点以分隔不同的线段
                  bool annotationSwitch = ref.read(annotationGraffitiSwitchProvider).annotationSwitch; // 底部开关是否打开
                  points.add(
                      GestureRecording(eraser: widget.graffitiSwitch.openEraser, annotationSwitch: annotationSwitch));
                  _isEraserPressed = false;
                  _eraserPosition = null;
                }
              },
              child: RepaintBoundary(
                key: widget.globalKey,
                child: CustomPaint(
                  isComplex: true,
                  willChange: true,
                  painter: DrawingPainter(
                    image: theImage,
                    points: points,
                    isErasing: widget.graffitiSwitch.openEraser,
                    destWidth: destWidth,
                    destHeight: destHeight,
                    imageWidth: imageWidth,
                    imageHeight: imageHeight,
                    homework: homework,
                    containerWidth: containerWidth,
                    containerHeight: containerHeight,
                  ),
                  //  size: Size(homework ? containerWidth : destWidth, homework ? containerHeight : destHeight),
                  size: Size(containerWidth, containerHeight),
                ),
              ),
            );
          },
        );
      },
    );
  }
}

class DrawingPainter extends CustomPainter {
  final List<GestureRecording> points;
  final bool isErasing;
  final ui.Image image;
  final bool homework;
  final double containerWidth;
  final double containerHeight;
  double destWidth;
  double destHeight;
  final double imageWidth;
  final double imageHeight;

  // final Rect destRect;
  // final Rect srcRect;
  final bool openErasing;
  DrawingPainter({
    required this.homework,
    required this.points,
    required this.isErasing,
    required this.image,
    required this.destWidth,
    required this.destHeight,
    required this.containerWidth,
    required this.containerHeight,
    required this.imageWidth,
    required this.imageHeight,
  })  :
        // destRect = Rect.fromLTWH(0, 0,destWidth,destHeight),
        // srcRect = Rect.fromLTWH(0, 0, imageWidth, imageHeight),
        openErasing = points.isNotEmpty && isErasing,
        super();

  Paint paintBrush = Paint()
    ..color = Colors.red
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 1.5;

  Paint eraser = Paint()
    ..blendMode = BlendMode.clear
    ..color = Colors.transparent
    ..style = PaintingStyle.stroke
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 100;

  final emptyPaint = Paint();
  final emptyPaintWithWidth = Paint()..strokeWidth = 60.0;

  @override
  void paint(Canvas canvas, Size size) {
    double offsetX = (size.width - destWidth) / 2;
    double offsetY = (size.height - destHeight) / 2;
    if (destWidth < (size.width / 2)) {
      destWidth = size.width / 2;
      offsetX = (size.width - destWidth) / 2;
    }

    // final rect = Rect.fromCenter(center: center, width: destWidth, height: destHeight);
    Rect srcRect = Rect.fromLTRB(0, 0, image.width.toDouble(), image.height.toDouble());
    // Rect destRect = Rect.fromLTRB(offsetX, offsetY, containerWidth, containerHeight);
    Rect destRect = Offset(offsetX, offsetY) & Size(destWidth, destHeight);

    canvas.drawImageRect(image, srcRect, destRect, emptyPaint);

    // canvas.drawImage(image, Offset.zero, emptyPaint);
    if (points.isNotEmpty) {
      // canvas.saveLayer(destRect, emptyPaintWithWidth);    // 只绘制图片大小区域
      canvas.saveLayer(Rect.largest, emptyPaintWithWidth); // 整个视图区域

      canvas.drawColor(Colors.transparent, BlendMode.clear);
    }

    for (int i = 0; i < points.length - 1; i++) {
      GestureRecording item = points[i];
      GestureRecording nextItem = points[i + 1];
      Offset? offsetData = item.data;
      Offset? nextOffsetData = nextItem.data;
      if (offsetData != null && nextOffsetData != null) {
        canvas.drawLine(offsetData, nextOffsetData, !item.eraser ? paintBrush : eraser);
      }
    }

    // 恢复画布状态.
    if (points.isNotEmpty) canvas.restore();
  }

  // @override
  // bool shouldRepaint(DrawingPainter oldDelegate) {
  //   List<GestureRecording> thePoints = oldDelegate.points;
  //   // var flag = oldDelegate.points != points || oldDelegate.isErasing != isErasing;
  //   return  thePoints != points;
  // }

  @override
  bool shouldRepaint(DrawingPainter oldDelegate) => true;
}
