/*
 * @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/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/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/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 'package:zoom_widget/zoom_widget.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;

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

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

class PictureOverviewState extends ConsumerState<PictureOverview> with CommonMixin {
  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; // 批注临时数据

  @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;
          Future.delayed(Duration(seconds: 5), () => 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);
    });
  }

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

  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 dpr = ui.window.devicePixelRatio;
        ui.Image image = await boundary.toImage(pixelRatio: dpr);
        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;
      }

      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 onScaleUpdate(double scale, double scale1) async {
    print('这是第一个scale：$scale');
    print('这是第二个noScale：$scale1');
    // 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: scale1,
      positionX: positionX,
      positionY: positionY,
      questionNum: widget.questionNum,
      markingUserId: widget.markingUserId,
    );
    FastData.getInstance().setMarkingZoomInfo(info);
  }

  @override
  Widget build(BuildContext context) {
    DoMarkingKeyboardModel _model = ref.watch(markingKeyboardProvider);
    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: (context, 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(),
                    );
                    printJson(imagInfoModel!.toJson());
                    Future.delayed(Duration.zero, () {
                      ref.read(zoomHeightProvider.notifier).setState(imagInfoModel?.scaleHeight ?? 0.0);
                    });
                  });
                  _imageStream = imageWidget.image.resolve(ImageConfiguration())..addListener(_imageStreamListener!);
                }

                // return imageWidget;
                return Zoom(
                  // initTotalZoomOut: true,
                  child: imageWidget,
                  maxZoomWidth: containerWidth,
                  canvasColor: Colors.transparent,
                  backgroundColor: Colors.transparent,
                  maxZoomHeight: imagInfoModel?.scaleHeight,
                  initScale: initScale ?? 1,
                  initPosition: zoomOffset,
                  // initPosition: ,
                  // onPositionUpdate: onPositionUpdate,
                  onScaleUpdate: onScaleUpdate,
                  // zoomSensibility: 0.5,
                );
              },
            );
          },
        ));
  }
}

// 试卷绘制
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);
                    points = List.from(points)
                      ..add(GestureRecording(eraser: widget.graffitiSwitch.openEraser, data: localPosition));
                    _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); // 增加空点以分隔不同的线段
                  points.add(GestureRecording(eraser: widget.graffitiSwitch.openEraser));
                  _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;
}

/**
 * 手势记录
 */
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),
          ],
        ),
      );
    },
  );

  // return Container(
  //   width: width,
  //   height: height,
  //   color: Colors.red,
  //   alignment: Alignment.center,
  //   child: tempFile != null
  //       ? Image.file(
  //           tempFile,
  //           fit: BoxFit.contain,
  //           width: double.infinity,
  //           height: double.infinity,
  //         )
  //       : CachedNetworkImage(
  //           key: _useImgRefsh.imageKey.value,
  //           fit: BoxFit.contain,
  //           width: double.infinity,
  //           // height: double.infinity,
  //           imageUrl: imageUrl,
  //           placeholder: (context, url) =>
  //               Center(child: SpinKitWave(color: Theme.of(context).primaryColor, size: 50.r)),
  //           // imageBuilder: (context, imageProvider) => Container(
  //           //   decoration: BoxDecoration(
  //           //     image: DecorationImage(
  //           //       image: imageProvider,
  //           //       fit: BoxFit.fitWidth,
  //           //       // colorFilter: ColorFilter.mode(Colors.red, BlendMode.colorBurn),
  //           //     ),
  //           //   ),
  //           // ),
  //           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 _useSwitch.showZoomImg.value
      ?
      /** 
      Scrollbar(
          // thumbVisibility: true,
          thumbVisibility: true,
          controller: _useScrollController,
          child: SingleChildScrollView(
            physics: AlwaysScrollableScrollPhysics(),
            padding: EdgeInsets.zero,
            scrollDirection: Axis.vertical, // 设置垂直滚动
            child: Transform.scale(
              scale: 0.4,
              alignment: Alignment.topCenter,
              child: $MyCachedNetworkImage(
                imageUrl: imageUrl,
                tempFile: _useSwitch.temFile.value,
                width: containerWidth,
                height: containerHeight,
              ),
            ),
          ),
        )*/

      /** */
      $MyCachedNetworkImage(
          imageUrl: imageUrl,
          tempFile: _useSwitch.temFile.value,
          width: containerWidth,
          height: containerHeight,
          imageBuilder: imageBuilder,
        )
      : ExamPaperDrawing(
          imgUrl: imageUrl,
          graffitiSwitch: graffitiSwitch,
          points: _useSwitch.points.value,
          pointsPureData: _useSwitch.pointsPureData.value,
          decoration: const BoxDecoration(color: const Color.fromRGBO(249, 250, 254, 1)),
          globalKey: theglobalKey,
          key: examGlobalKey,
          imageLoaded: _useSwitch.imageLoaded,
          homework: homework,
          // imageCall: (String str) => widget.imageCall(str, currentIndex),
        );
}

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?.points;
        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;
  }
}
