/*
 * @Author: wangyang 1147192855@qq.com
 * @Date: 2022-07-23 11:55:16
 * @LastEditors: wangyang 1147192855@qq.com
 * @LastEditTime: 2022-09-28 17:01:15
 * @FilePath: \marking_app\lib\components\PictureOverview.dart
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import 'dart:async';
import 'dart:io';
import 'package:crypto/crypto.dart' as crypto;

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:marking_app/common/mixin/common.dart';
import 'package:marking_app/common/model/common/base_structure_result.dart';
import 'package:marking_app/common/model/common/upload_img_secret_key.dart';
import 'package:marking_app/common/model/enum/review_marks_bottom_btns_enum.dart';
import 'package:marking_app/common/model/event_bus/bottom_annotation_switch_cleanall.dart';
import 'package:marking_app/common/model/job/test_questions_image_info.dart';
import 'package:marking_app/common/model/job/upload_file_interface_config.dart';
import 'package:marking_app/common/model/job/upload_file_interface_config_params.dart';
import 'package:marking_app/common/model/marking/annotation_graffiti_switch.dart';
import 'package:marking_app/common/model/marking/do_marking_keyboard_model.dart';
import 'package:marking_app/common/model/marking/marking_history_zoom_info.dart';
import 'package:marking_app/common/model/marking/marking_text_question.dart';
import 'package:marking_app/common/model/marking/switch_keyboard_to_reload_images.dart';
import 'package:marking_app/pages/common/event_bus_mixin.dart';
import 'package:marking_app/pages/homework_correction/hooks/use_cached_img_refresh.dart';
import 'package:marking_app/pages/marking/hooks/use_zoom_image_history.dart';
import 'package:marking_app/pages/marking/provider/do_paper_bottom_review_marks_provider.dart';
import 'package:marking_app/pages/marking/provider/zoom_height_provider.dart';
import 'package:marking_app/pages/marking/provider/zoom_history_provider.dart';
import 'package:marking_app/provider/annotation_graffiti_switch_provider.dart';
import 'package:marking_app/provider/do_marking_provider.dart';
import 'package:marking_app/provider/upload_file_provider.dart';
import 'package:marking_app/utils/index.dart';
import 'package:marking_app/utils/my_text.dart';
import 'package:marking_app/utils/request/rest_client.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:ui' as ui;

import 'package:uuid/uuid.dart';
import 'package:zoom_widget/zoom_widget.dart';

import '../pages/marking/provider/draw_marking_provider.dart';
part 'PictureOverview.g.dart';

typedef PageChanged = void Function(int index);

//这里就是关键的代码，定义一个key
final GlobalKey<PictureOverviewState> pictureOverviewKey = GlobalKey<PictureOverviewState>();

class PictureOverview extends StatefulHookConsumerWidget {
  final double imageScale;
  final Offset? imagePosition;

  final String questionNum;
  final int markingUserId;

  final bool homework;
  final List imageItems; //图片列表
  final bool annotationsFlag;
  final String testQuestionNumber;
  final Map<String, String> commentImageMap;
  final MarkingTextQuestion data;
  final Function callAnnotationTips;

  const PictureOverview({
    required this.imageItems,
    required this.annotationsFlag,
    required this.commentImageMap,
    required this.testQuestionNumber,
    required this.questionNum,
    required this.markingUserId,
    required this.data,
    required this.callAnnotationTips,
    this.homework = false,
    this.imageScale = 1,
    this.imagePosition,
    Key? key,
  }) : super(key: key);

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

class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMixin, EventBusMixin {
  final GlobalKey theglobalKey = GlobalKey();
  final GlobalKey<_ExamPaperDrawingState> examPaperDrawingKey = GlobalKey<_ExamPaperDrawingState>();
  final GlobalKey zoomGlobalKey = GlobalKey(); // zoom
  double? initScale;
  Offset? zoomOffset;

  ImageStreamListener? _imageStreamListener;
  TestQuestionsImageInfo? imagInfoModel; // 试题图片数据
  ImageStream? _imageStream;

  final int currentIndex = 0;
  late AnnotationGraffitiSwitch graffitiSwitch;
  late RemoveListener _annotationsListener; // 批注关闭监听
  File? temFile; // 批注临时数据

  // 用于记录绘图结果的变量
  Offset? globalPosition; // 是否正在绘制
  MarkingHistoryZoomInfo? zoomInfo;
  bool illegalArea = false; // 非法区域（批阅笔迹不在试题图片中）
  final GlobalKey _zoomKey = GlobalKey<State<Zoom>>();

  @override
  void initState() {
    super.initState();
    FastData.getInstance().getMarkingZoomInfo().then((value) {
      if (value == null) return;
      bool flag = value.questionNum == widget.questionNum && value.markingUserId == widget.markingUserId;
      if (flag) {
        if (value.positionX != 0 && value.positionY != 0) {
          // zoomOffset = Offset(value.positionX, value.positionY);
        }
        if (value.scale < 1) {
          initScale = value.scale;
          // 5
          Future.delayed(Duration(seconds: 1), () => ref.read(zoomHistoryProvider.notifier).setState(initScale!));
        }
      }
    });
    Future.delayed(Duration.zero, () {
      ref.read(zoomHeightProvider.notifier).setState(0.0);
    });
    _annotationsListener = ref.read(annotationGraffitiSwitchProvider.notifier).addListener((state) {
      graffitiSwitch = state;
      toUpState(setState, () {}, mounted);
    });

    // 事件总线监听  清空数据
    eventOn(callback: (BottomAnnotationSwitchCleanallOfMarking item) async {
      widget.callAnnotationTips(); // 调用回调 通知父级批注记录被更改
      if (ref.read(drawMarkingProvider).data.isEmpty) {
        if (widget.data.commentImageUrl.isNotEmpty) {
          bool? res = await showDialog<bool>(
            // 表示点击灰色背景的时候是否消失弹出框
            barrierDismissible: false,
            context: context,
            builder: (context1) {
              return AlertDialog(content: quickText("是否撤销上次批阅批注痕迹"), actions: <Widget>[
                TextButton(child: quickText("取消"), onPressed: () => Navigator.pop(context1, false)),
                TextButton(child: quickText("确定", color: Theme.of(context).primaryColor), onPressed: () => Navigator.pop(context1, true))
              ]);
            },
          );
          if (res == true) {
            widget.data.commentImageUrl.removeAt(currentIndex);
            var theUrl = widget.imageItems[currentIndex];
            widget.commentImageMap[theUrl] = theUrl;
            toUpState(setState, () {}, mounted);
          }
        } else {
          ToastUtils.showInfo('批注已清空');
        }
      }
    });
  }

  @override
  void dispose() {
    _annotationsListener();
    eventCancel();
    try {
      _imageStream?.removeListener(_imageStreamListener!);
      if (temFile != null) {
        bool flieExist = temFile!.existsSync();
        if (flieExist) temFile!.delete();
      }
      // if (zoomOffset != null) saveZoomPosition();
    } catch (e) {}
    super.dispose();
  }

  Future<FileResult?> saveImage() async {
    try {
      ToastUtils.showLoading();
      if (temFile == null) {
        if (examPaperDrawingKey.currentState?.pointsPureData.isEmpty ?? true) return null;
        // 没有图片就上传图片
        RenderRepaintBoundary? boundary = theglobalKey.currentContext!.findRenderObject() as RenderRepaintBoundary?;
        if (boundary == null) return null;
        // double dpr = MediaQuery.of(context).devicePixelRatio;

        double pixelRatio = MediaQuery.of(context).devicePixelRatio;
        if (imagInfoModel?.pixelRatio != null) pixelRatio = imagInfoModel!.pixelRatio;

        ui.Image image = await boundary.toImage(pixelRatio: pixelRatio);
        ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
        if (byteData == null) {
          /// 等于null 已经是异常了
          return null;
        }
        Directory appDocDir = await getApplicationDocumentsDirectory();
        List<int> bytes = byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes);
        String filePath = '${appDocDir.path}/${Uuid().v1()}.png'; // 文件路径及名称
        File file = File(filePath); // 创建文件对象
        await file.writeAsBytes(bytes); // 将ByteData写入文件
        temFile = file;
      }

      if (imagInfoModel != null) {
        // 剪切图片
      }

      crypto.Digest fileMd5 = crypto.md5.convert(await temFile!.readAsBytes());
      RestClient _client = await getClient();
      BaseStructureResult<UploadFileInterfaceConfig> resUploadConfig = await _client.getUploadFile(UploadFileInterfaceConfigParams(
        fileName: '1.png',
        fileMd5: fileMd5.toString(),
        contentLength: temFile!.lengthSync(),
      ));
      if (!resUploadConfig.success || resUploadConfig.data == null) {
        ToastUtils.getFluttertoast(msg: '获取图片上传配置失败', context: context);

        return null;
      }
      if (resUploadConfig.data!.uploadUri == null) {
        return FileResult(myObject: '', success: true, url: resUploadConfig.data!.downloadUri);
      }
      FileResult? resFile = await ref.read(uploadFileProvider.notifier).getUploadFileConfig(resUploadConfig.data!, temFile!);
      // FileResult? resFile = await ref
      //     .read(uploadFileProvider.notifier)
      //     .uploadFile(temFile!.path, widget.imageItems[currentIndex], ref.read(userProvider).id.toString());
      if (resFile != null && resFile.success) {
        resFile.otherParam = currentIndex;
        return resFile;
      }
    } catch (e) {
      toPrint(val: e.toString());
    } finally {
      // ToastUtils.dismiss();
    }
    return null;
  }

  // 缩放组件 ==> 位置更新
  void onPositionUpdate(Offset position) async {
    MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
    double? scale = historyZoomInfo?.scale ?? 1;
    MarkingHistoryZoomInfo info = MarkingHistoryZoomInfo(
      scale: scale,
      positionX: position.dx,
      positionY: position.dy,
      questionNum: widget.questionNum,
      markingUserId: widget.markingUserId,
    );
    FastData.getInstance().setMarkingZoomInfo(info);
  }

  void saveZoomPosition() async {
    MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
    if (historyZoomInfo != null) {
      FastData.getInstance().setMarkingZoomInfo(MarkingHistoryZoomInfo(
        scale: historyZoomInfo.scale,
        positionX: zoomOffset!.dx,
        positionY: zoomOffset!.dy,
        questionNum: historyZoomInfo.questionNum,
        markingUserId: historyZoomInfo.markingUserId,
      ));
    }
  }

  void onPanUpPosition(Offset val) async {
    // 手指在移动 非物体移动的位置
    // print('**************** 正在移动位置 YYY:${val.dy}');
    // print('**************** 正在移动位置 XXX:${val.dx}');
    zoomOffset = val;
  }

  // 缩放组件 ==> 缩放监听
  void onScaleUpdate(double scale, double zoom) async {
    // print('zoom：$zoom');
    // print('scale：${scale}');
    // MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
    MarkingHistoryZoomInfo? historyZoomInfo = await FastData.getInstance().getMarkingZoomInfo();
    double positionX = historyZoomInfo?.positionX ?? 0;
    double positionY = historyZoomInfo?.positionY ?? 0;
    MarkingHistoryZoomInfo info = MarkingHistoryZoomInfo(
      scale: zoom,
      positionX: positionX,
      positionY: positionY,
      questionNum: widget.questionNum,
      markingUserId: widget.markingUserId,
    );
    zoomInfo = info;
    // if (double.parse(zoom.toStringAsFixed(2)) <= 1) zoom = 1;
    if (imagInfoModel != null) {
      // 根据缩放比例重置被放大的图片的尺寸
      imagInfoModel = TestQuestionsImageInfo(
        // 获取图片的宽高
        boxHeight: imagInfoModel!.boxHeight,
        boxWidth: imagInfoModel!.boxWidth,
        url: imagInfoModel!.url,
        height: imagInfoModel!.height,
        width: imagInfoModel!.width,
        zoom: zoom,
      );
    }
    FastData.getInstance().setMarkingZoomInfo(info);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
        width: double.infinity,
        height: double.infinity,
        alignment: Alignment.center,
        child: LayoutBuilder(
          builder: (BuildContext context, BoxConstraints constraints) {
            double containerWidth = constraints.maxWidth;
            double containerHeight = constraints.maxHeight;

            return $LocalAndNetworkSwitch(
              zoomGlobalKey: zoomGlobalKey,
              containerWidth: containerWidth,
              containerHeight: containerHeight,
              imagePosition: widget.imagePosition ?? Offset(0, 0),
              imageScale: widget.imageScale,
              homework: widget.homework,
              theglobalKey: theglobalKey,
              graffitiSwitch: graffitiSwitch,
              drawFlag: widget.annotationsFlag,
              examGlobalKey: examPaperDrawingKey,
              testQuestionNumber: widget.testQuestionNumber,
              imageUrl: widget.commentImageMap[widget.imageItems[currentIndex]]!,
              updateTempFileCall: (File? file) {
                temFile = file;
                print('更新需要上传的文件');
              },
              imageBuilder: (imageBuilderContext, imageProvider) {
                Image imageWidget = Image(image: imageProvider, fit: BoxFit.fitWidth);
                if (imagInfoModel == null || (imagInfoModel?.boxHeight != containerHeight || imagInfoModel?.boxWidth != containerWidth)) {
                  if (_imageStreamListener != null) _imageStream?.removeListener(_imageStreamListener!);
                  _imageStreamListener = ImageStreamListener((ImageInfo info, bool _) {
                    imagInfoModel = TestQuestionsImageInfo(
                      // 获取图片的宽高
                      boxHeight: containerHeight,
                      boxWidth: containerWidth,
                      url: widget.commentImageMap[widget.imageItems[currentIndex]]!,
                      height: info.image.height.toDouble(),
                      width: info.image.width.toDouble(),
                    );
                    Future.delayed(Duration.zero, () {
                      ref.read(zoomHeightProvider.notifier).setState(imagInfoModel?.scaleHeight ?? 0.0);
                    });
                  });
                  _imageStream = imageWidget.image.resolve(ImageConfiguration())..addListener(_imageStreamListener!);
                }

                var btnEnum = ref.watch(doPaperBottomReviewMarksProvider);
                // return imageWidget;
                return Listener(
                  behavior: HitTestBehavior.opaque,
                  onPointerMove: (PointerMoveEvent details) {
                    if (btnEnum != ReviewMarksBottomBtnsEnum.HANDWRITING) return;
                    if (globalPosition != null) {
                      // 预防双指同时作用于屏幕
                      double dx = globalPosition!.dx;
                      double dy = globalPosition!.dy;

                      double dxNew = details.localPosition.dx;
                      double dyNew = details.localPosition.dy;
                      if ((dxNew - dx).abs() > 22 || (dyNew - dy).abs() > 22) return;
                    }
                    globalPosition = details.localPosition;
                    Offset localPosition = globalPosition!;

                    // if (imagInfoModel != null &&
                    //     (localPosition.dy < imagInfoModel!.imageHeightOffsetStart! || localPosition.dy > imagInfoModel!.imageHeightOffsetend!)) {
                    //   // 笔迹画出图片区域 直接断笔
                    //   var dataVal = ref.read(drawMarkingProvider).data;
                    //   if (dataVal.length - 1 > -1 && dataVal[dataVal.length - 1].data != null) {
                    //     var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser));
                    //     var newVal1 = ref.read(drawMarkingProvider).offsets..add(null);
                    //     ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
                    //   }
                    //   illegalArea = true;
                    //   return;
                    // }
                    // illegalArea = false;

                    var _theKey = _zoomKey.currentState;
                    print(_theKey);

                    double remainingHeight = imagInfoModel!.imageHeightOffsetStart!; // 剩余高度
                    if (remainingHeight > 1) {
                      localPosition = Offset(localPosition.dx, localPosition.dy - remainingHeight);
                    }

                    // print(localPosition.dy);
                    print(localPosition.dx);

                    double _theZoomVal = imagInfoModel?.zoom ?? 1;
                    var _dx = zoomOffset?.dx ?? 0;
                    _dx = _dx > 0 ? 0 : _dx.abs() / _theZoomVal;
                    var _dy = zoomOffset?.dy ?? 0;
                    _dy = _dy > 0 ? 0 : _dy.abs() / _theZoomVal;

                    if (_theZoomVal > 1) {
                      // 计算视图被放大比例 还原笔迹坐标
                      localPosition = Offset(localPosition.dx / _theZoomVal, localPosition.dy / _theZoomVal);
                      if (zoomOffset != null) {
                        // 如果滚动条有触动就加上滚动条滚动的位置
                        localPosition = Offset(localPosition.dx + _dx, localPosition.dy + _dy);
                      }
                    } else if (_theZoomVal < 1) {
                      // 试图被缩小
                      double imgSpaceWidthOfSingle = (imagInfoModel!.boxWidth - imagInfoModel!.scaleWidth!) / 2;
                      localPosition = Offset((localPosition.dx - imgSpaceWidthOfSingle) / _theZoomVal, localPosition.dy / _theZoomVal + _dy);
                      // localPosition = Offset(localPosition.dx * _theZoomVal - imgSpaceWidthOfSingle, localPosition.dy / _theZoomVal);
                    } else {
                      localPosition = Offset(localPosition.dx, localPosition.dy + _dy);
                    }

                    var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser, data: localPosition));
                    var newVal1 = ref.read(drawMarkingProvider).offsets..add(localPosition);
                    ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
                    widget.callAnnotationTips();
                  },
                  // onPointerDown: (PointerDownEvent event) {
                  // },
                  onPointerUp: (PointerUpEvent details) {
                    if (btnEnum != ReviewMarksBottomBtnsEnum.HANDWRITING) return;
                    // 如果在空白区域 非试题图片区域就返回
                    if (illegalArea) return;

                    globalPosition = null;

                    var newVal = ref.read(drawMarkingProvider).data..add(GestureRecording(eraser: graffitiSwitch.openEraser));
                    var newVal1 = ref.read(drawMarkingProvider).offsets..add(null);
                    ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(newVal, newVal1));
                  },
                  child: IgnorePointer(
                    ignoring: btnEnum != ReviewMarksBottomBtnsEnum.DRAG,
                    child: Zoom(
                      key: _zoomKey,
                      // initTotalZoomOut: true,
                      child: ExamPaperDrawing(
                        key: examPaperDrawingKey,
                        globalKey: theglobalKey,
                        child: imageWidget,
                        graffitiSwitch: graffitiSwitch,
                        decoration: const BoxDecoration(color: const Color.fromRGBO(249, 250, 254, 1)),
                      ),
                      maxZoomWidth: containerWidth,
                      canvasColor: Colors.transparent,
                      backgroundColor: Colors.transparent,
                      maxZoomHeight: imagInfoModel?.scaleHeight != null ? (imagInfoModel!.scaleHeight! / imagInfoModel!.zoom) : null,
                      initScale: initScale ?? 1,
                      initPosition: zoomOffset,
                      onScaleUpdate: onScaleUpdate,
                      onPositionUpdate: onPanUpPosition,
                    ),
                  ),
                );
              },
            );
          },
        ));
  }
}

// 试卷绘制
class ExamPaperDrawing extends StatefulHookConsumerWidget {
  // String imgUrl;
  Widget child;
  BoxDecoration? decoration;
  AnnotationGraffitiSwitch graffitiSwitch;
  GlobalKey globalKey;
  // Function(String) imageCall;
  ExamPaperDrawing({
    // required this.imgUrl,
    required this.child,
    required this.graffitiSwitch,
    required this.globalKey,
    this.decoration,
    Key? key,
  }) : super(key: key);

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

class _ExamPaperDrawingState extends ConsumerState<ExamPaperDrawing> with EventBusMixin<BottomAnnotationSwitchCleanallOfMarking> {
  // 用于记录手指位置的变量
  late RemoveListener removeListener;
  late ValueNotifier<List<GestureRecording>> _vnHandWritings;
  late List<Offset?> pointsPureData = [];

  @override
  void initState() {
    _vnHandWritings = ValueNotifier<List<GestureRecording>>([]);
    removeListener = ref.read(drawMarkingProvider.notifier).addListener((state) {
      pointsPureData = state.offsets;
      _vnHandWritings.value = [...state.data];
    }, fireImmediately: false);

    // 事件总线监听
    eventOn(callback: (BottomAnnotationSwitchCleanallOfMarking item) {
      if (item.previousStep) {
        if (ref.read(drawMarkingProvider).data.isEmpty) {
          return;
        }
        var index = pointsPureData.toList().lastIndexOf(null);
        if (index != -1) {
          if (index + 1 == pointsPureData.length) {
            pointsPureData = pointsPureData.sublist(0, index);

            ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(ref.read(drawMarkingProvider).data.sublist(0, index), pointsPureData));
            index = pointsPureData.toList().lastIndexOf(null);
            index == -1 ? -1 : index + 1;
          }
          if (index != -1) {
            pointsPureData = pointsPureData.sublist(0, index);
            ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal(ref.read(drawMarkingProvider).data.sublist(0, index), pointsPureData));
          } else {
            item.cleanAll = true;
          }
        } else {
          item.cleanAll = true;
        }
      }

      if (item.cleanAll) {
        pointsPureData.clear();
        ref.read(drawMarkingProvider.notifier).setState(DrawMarkingVal([], []));
      }
    });
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    print('_ExamPaperDrawingState的build....');

    return RepaintBoundary(
      key: widget.globalKey,
      child: CustomPaint(
        isComplex: true,
        willChange: true,
        foregroundPainter: DrawingPainter(ctrl: _vnHandWritings),
        child: widget.child,
      ),
    );
  }
}

class DrawingPainter extends CustomPainter {
  final ValueNotifier<List<GestureRecording>> ctrl;
  final Paint paintBrush = Paint();
  DrawingPainter({required this.ctrl}) : super(repaint: ctrl) {
    paintBrush
      ..color = Colors.red
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 1.5.r;
  }

  @override
  void paint(Canvas canvas, Size size) {
    var points = ctrl.value;
    var pointsLength = points.length;
    print('数据.....................[[[[[${points.length}]]]]]');
    for (int i = 0; i < pointsLength; i++) {
      GestureRecording item = points[i];
      Offset? offsetData = item.data;
      Offset? nextOffsetData = pointsLength - 1 == i ? null : points[i + 1].data;
      if (offsetData != null && nextOffsetData != null) {
        canvas.drawLine(offsetData, nextOffsetData, paintBrush);
      }
    }
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    print('FFFFFF55555555555555');
    // if (oldDelegate is DrawingPainter) {
    //   var repaint = ctrl.value.length != oldDelegate.ctrl.value.length || oldDelegate.ctrl.value != ctrl.value;
    //   print('调用是否绘制：$repaint');

    //   return repaint;
    // }

    return false;
  }
}

/**
 * 手势记录
 */
class GestureRecording {
  bool eraser; // 是否是橡皮擦

  Offset? data; // 位置记录 可能为null

  GestureRecording({required this.eraser, this.data});
}

@hwidget
Widget $myCachedNetworkImage({
  required String imageUrl,
  required File? tempFile,
  required double width,
  required double height,
  required ImageWidgetBuilder? imageBuilder,
}) {
  UseCachedImgRefresh _useImgRefsh = UseCachedImgRefresh.use();

  if (tempFile != null) {
    // 注释临时本地图片
    return Image.file(tempFile, fit: BoxFit.contain, width: double.infinity, height: double.infinity);
  }

  useEffect(() {
    _useImgRefsh.eventOnSub<SwitchKeyboardToReloadImages>(callback: (SwitchKeyboardToReloadImages event) {
      if (event.reload) {
        _useImgRefsh.imageKey.value = UniqueKey();
      }
    });

    return () {
      _useImgRefsh.eventCancelSub();
    };
  }, []);

  return CacheNetImageView(
    cacheNetImageKey: _useImgRefsh.imageKey.value,
    imageUrl: imageUrl,
    imageBuilder: imageBuilder,
    errorWidget: (context, url, error) {
      return GestureDetector(
        onTap: () => (_useImgRefsh.imageKey.value = UniqueKey()),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Image.asset('assets/images/test_paper_loading_failed.png'),
            quickText('加载失败，点击重试', color: Color.fromRGBO(148, 163, 182, 1), size: 12.sp),
          ],
        ),
      );
    },
  );
}

class CacheNetImageView extends ConsumerWidget {
  final Key cacheNetImageKey;
  final String imageUrl;
  final ImageWidgetBuilder? imageBuilder;
  final LoadingErrorWidgetBuilder? errorWidget;
  const CacheNetImageView({
    required this.cacheNetImageKey,
    required this.imageUrl,
    required this.imageBuilder,
    required this.errorWidget,
    super.key,
  });

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    double zoomHeight = ref.watch(zoomHeightProvider);
    double initScale = ref.watch(zoomHistoryProvider);

    print('zoomView的视图最大高度:$zoomHeight 和 缩放比例$initScale');
    return CachedNetworkImage(
      key: cacheNetImageKey,
      imageUrl: imageUrl,
      fit: BoxFit.fitWidth,
      width: double.infinity,
      alignment: Alignment.center,
      imageBuilder: imageBuilder,
      placeholder: (context, url) => Center(child: SpinKitWave(color: Theme.of(context).primaryColor, size: 50.r)),
      errorWidget: errorWidget,
    );
  }
}

// double zoomHeight = ref.watch(zoomHeightProvider);

/// 网络图和本地图切换
@hwidget
Widget $localAndNetworkSwitch(
  BuildContext context, {
  double imageScale = 1,
  Offset imagePosition = const Offset(0, 0),
  required ImageWidgetBuilder? imageBuilder,
  required GlobalKey zoomGlobalKey,
  required double containerWidth,
  required double containerHeight,
  required String testQuestionNumber, // 试题题号
  required String imageUrl, // 图片
  required bool drawFlag, // 是否打开绘画操作
  required GlobalKey theglobalKey,
  required bool homework,
  required GlobalKey<_ExamPaperDrawingState> examGlobalKey,
  required AnnotationGraffitiSwitch graffitiSwitch,
  required Function(File?) updateTempFileCall,
}) {
  // ImageStream? imageStream; // 图片监听数据
  // TestQuestionsImageInfo? imagInfoModel; // 试题图片数据
  // ImageStreamListener theImageStreamListener;

  UseLocalAndNetworkSwitch _useSwitch = UseLocalAndNetworkSwitch.use(!homework);
  UseZoomImageHistory _useZoomHistory = UseZoomImageHistory.use(testQuestionNumber);

  // TransformationController _transContller = useTransformationController();

  useValueChanged<File?, String>(
    _useSwitch.temFile.value,
    (oldValue, oldResult) {
      updateTempFileCall(_useSwitch.temFile.value);
      return null;
    },
  );

  useValueChanged<String, String>(testQuestionNumber, (oldValue, oldResult) {
    if (testQuestionNumber.length > 0) {
      _useZoomHistory.initInfo(testQuestionNumber);
    }
  });

  useValueChanged<bool, String>(drawFlag, (oldValue, oldResult) {
    if (!drawFlag) {
      // 关闭的时候创建临时图片文件在设备
      _useSwitch.createTempFile(context, theglobalKey: theglobalKey, examGlobalKey: examGlobalKey).then((File? theFile) {
        if (theFile == null) {
          // TODO 代表保存失败的逻辑
          // 当前情况：_useSwich.showZoomImg.value 没有设置为true还是展示的原来的绘图组件ExamPaperDrawing
          toPrint(val: '进入错误逻辑.........');
        }
        _useSwitch.showZoomImg.value = true;
      });
      return;
    }
    _useSwitch.showZoomImg.value = !drawFlag;
  });
  useEffect(() {
    _useZoomHistory.initInfo(); // 初始化历史数据

    // _useScrollController
    //   ..addListener(() {
    //     _scrollPosition.value = _useScrollController.position.pixels;
    //   });
    return () {
      // try {
      //   _useImageSize.imageStream.value?.removeListener(_useImageSize.imageListener.value!);
      // } catch (e) {}
      // ..removeListener(() {})
    };
  }, []);

  print('是否更新视图.... ${_useZoomHistory.initPosition.value}');
  return $MyCachedNetworkImage(
    imageUrl: imageUrl,
    tempFile: _useSwitch.temFile.value,
    width: containerWidth,
    height: containerHeight,
    imageBuilder: imageBuilder,
  );
}

class UseLocalAndNetworkSwitch {
  ValueNotifier<bool> showZoomImg;
  ValueNotifier<File?> temFile;

  ValueNotifier<List<GestureRecording>?> points;
  ValueNotifier<List<dynamic>?> pointsPureData;
  ValueNotifier<Map<String, ui.Image>> imageLoaded;

  UseLocalAndNetworkSwitch._({
    required this.showZoomImg,
    required this.temFile,
    required this.points,
    required this.pointsPureData,
    required this.imageLoaded,
  });

  // 工厂构造函数
  factory UseLocalAndNetworkSwitch.use(bool defaultVal) {
    return UseLocalAndNetworkSwitch._(
      points: useState(null),
      pointsPureData: useState(null),
      showZoomImg: useState(defaultVal),
      temFile: useState(null),
      imageLoaded: useState({}),
    );
  }

  Future<File?> createTempFile(
    BuildContext context, {
    required GlobalKey theglobalKey,
    required GlobalKey<_ExamPaperDrawingState> examGlobalKey,
  }) async {
    Timer? _timer;
    try {
      _timer = Timer(Duration(seconds: 1), () {
        // 执行操作的代码
        ToastUtils.showLoading();
      });
      if (examGlobalKey.currentState?.pointsPureData.isEmpty ?? true) {
        try {
          temFile.value?.delete();
        } catch (e) {}
        temFile.value = null;
        return null;
      }

      RenderRepaintBoundary? boundary = theglobalKey.currentContext!.findRenderObject() as RenderRepaintBoundary?;
      if (boundary == null) return null;
      ui.Image image = await boundary.toImage(pixelRatio: 3.0);
      ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      if (byteData != null) {
        Directory appDocDir = await getApplicationDocumentsDirectory();
        List<int> bytes = byteData.buffer.asUint8List(byteData.offsetInBytes, byteData.lengthInBytes);
        String filePath = '${appDocDir.path}/${Uuid().v1()}.png'; // 文件路径及名称
        File file = File(filePath); // 创建文件对象
        await file.writeAsBytes(bytes); // 将ByteData写入文件

        temFile.value?.delete();
        temFile.value = file; // 保存临时文件

        points.value = examGlobalKey.currentState?._vnHandWritings.value;
        pointsPureData.value = examGlobalKey.currentState?.pointsPureData;
        toPrint(val: '图片保存成功：');
        return temFile.value;
      }
    } catch (e) {
      toPrint(val: '图片生成错误：${e}');
      toPrint(val: e.toString());
      ToastUtils.getFluttertoast(context: context, msg: '保存图片报错，请稍后重试');
    } finally {
      _timer?.cancel();
      ToastUtils.dismiss();
    }
    return null;
  }
}
