import 'dart:async';

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.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/model/job/gesture_recording.dart';
import 'package:marking_app/common/model/job/job_note_taking_trajectory.dart';
import 'package:marking_app/common/model/job/test_questions_image_info.dart';
import 'package:marking_app/pages/homework_correction/hooks/use_cached_img_refresh.dart';
import 'package:marking_app/pages/homework_correction/providers/drawing_trajectory_provider.dart';
import 'package:marking_app/utils/my_text.dart';

part 'trajectoryView.g.dart';

class TrajectoryView extends StatefulHookConsumerWidget {
  final double boxWidth;
  final double boxHeight;
  final String questionNumber;
  final JobNoteTakingTrajectory trajectory;
  const TrajectoryView(
      {required this.trajectory,
      required this.questionNumber,
      required this.boxHeight,
      required this.boxWidth,
      super.key});

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

class TrajectoryViewState extends ConsumerState<TrajectoryView> {
  String? oldQuestionNumber;
  ImageStream? imageStream; // 图片监听数据
  TestQuestionsImageInfo? imagInfoModel; // 试题图片数据
  late ImageStreamListener theImageStreamListener;
  dynamic delayedFuture;
  List<Timer>? delayedCalls;

  @override
  void initState() {
    super.initState();
    oldQuestionNumber = widget.questionNumber;

    theImageStreamListener = ImageStreamListener((ImageInfo info, bool _) {
      if (imagInfoModel != null && widget.questionNumber == oldQuestionNumber) return;
      oldQuestionNumber = widget.questionNumber;
      imagInfoModel = TestQuestionsImageInfo(
        // 获取图片的宽高
        boxHeight: widget.boxHeight,
        boxWidth: widget.boxWidth,
        url: widget.trajectory.paperPicture,
        height: info.image.height.toDouble(),
        width: info.image.width.toDouble(),
      );
      getCalculatedSize(widget.questionNumber);
    });
    imageStream?.removeListener(theImageStreamListener);
  }

  ddd() async {
    await Future.doWhile(() async {
      return false;
    });
  }

  @override
  void dispose() {
    print('销毁笔记回显页面.....................');
    super.dispose();
    try {
      imageStream?.removeListener(theImageStreamListener);
    } catch (e) {}
  }

  // ignore: slash_for_doc_comments
  /**
  Future<void> zhixinCall(
    List<GestureRecording> trajectorys,
    List<Lattices>? nextStrokesData,
    GestureRecording theRecording,
    GestureRecording nextRecording,
  ) async {
    var duration1 = Duration(milliseconds: theRecording.usageTime!);
    var duration2 = nextRecording.usageTime != null ? Duration(milliseconds: nextRecording.usageTime!) : null;
    var differenceInMilliseconds = 0;
    if (duration2 != null) differenceInMilliseconds = (duration2 - duration1).inMilliseconds;
    await Future.delayed(Duration(milliseconds: differenceInMilliseconds));
    if (mounted) {
      ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys..add(theRecording));
    }
    if (duration2 == null && nextStrokesData != null) {
      // 此时最后一个笔画完成了 停止时间是在下一个笔画开始时间之差
      Lattices minLattices = nextStrokesData.reduce((e1, e2) => e1.time < e2.time ? e1 : e2);
      differenceInMilliseconds = (Duration(milliseconds: minLattices.time.toInt()) - duration1).inMilliseconds;
      // 加此句代码就是每一笔的停顿时间 ，不加就是每一笔不停顿
      await Future.delayed(Duration(milliseconds: differenceInMilliseconds)); // 一个笔画完成进行下一个笔画的等待时间
    }
  } 
  */

  // 计算尺寸
  Future<void> getCalculatedSize(String questionNumber) async {
    if (imagInfoModel == null) return;
    double width = imagInfoModel!.width;
    double height = imagInfoModel!.height;
    double imageScale = width / height;
    double imageScaleFixed = double.parse(imageScale.toStringAsFixed(2));

    double boxWidth = imagInfoModel!.boxWidth;
    double boxHeight = imagInfoModel!.boxHeight;
    double boxScale = boxWidth / boxHeight;
    double boxScaleFixed = double.parse(boxScale.toStringAsFixed(2));

    double theScaleDifference = boxScaleFixed - imageScaleFixed; // 相差

    if (imagInfoModel!.scaleHeight! > boxHeight) {
      // 默认比例计算为宽铺满屏幕,但是宽铺满屏幕高要超出，所以为全屏展示完整图片就高为基准 缩放图片 重置倍数
      imagInfoModel!.scale = imagInfoModel!.boxHeight / height; // 缩放倍数
      imagInfoModel!.scaleWidth = imagInfoModel!.scale! * width;
      imagInfoModel!.scaleHeight = imagInfoModel!.scale! * height;
      getCalculatedSize(questionNumber);
    } else if (imagInfoModel!.scaleHeight! < boxHeight) {
      // 默认计算模式
    } else {}

    double spacingHeight = 0;
    double spacingWidth = 0;

    if (theScaleDifference > 0) {
      // 容器大于图片宽高比例 则图片将以高度为基准进行拉伸，以适应容器的高度。
      if (imagInfoModel!.scaleWidth! < imagInfoModel!.boxWidth) {
        spacingWidth = (imagInfoModel!.boxWidth - imagInfoModel!.scaleWidth!) / 2;
      }
    } else if (theScaleDifference < 0) {
      // 容器小于图片宽高比例， 则图片将以宽度为基准进行拉伸，以适应容器的宽度。
      if (imagInfoModel!.scaleHeight! < imagInfoModel!.boxHeight) {
        spacingHeight = (imagInfoModel!.boxHeight - imagInfoModel!.scaleHeight!) / 2;
      }
    } else {
      // 容器等于图片比例  图片会拉升或者缩小图片铺满整个容器 此时图片展示宽高就等于容器宽高
    }
    List<GestureRecording> trajectorys = [];

    var trajectory = widget.trajectory;
    List<Lattices> lattices = trajectory.lattices;
    trajectory.pictureQuestionTop = trajectory.pictureQuestionTop * imagInfoModel!.scale! + spacingHeight;
    trajectory.pictureQuestionHeight = trajectory.pictureQuestionHeight * imagInfoModel!.scale!;

    /// 试题范围框左上角
    trajectorys
      ..add(GestureRecording(
          data: Offset(2.w, trajectory.pictureQuestionTop), scopeBox: true, annotationSwitch: false, eraser: false))

      /// 右上角
      ..add(GestureRecording(
          data: Offset(imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop),
          scopeBox: true,
          annotationSwitch: false,
          eraser: false))

      /// 左下角
      ..add(GestureRecording(
          data: Offset(2.w, trajectory.pictureQuestionTop + trajectory.pictureQuestionHeight),
          scopeBox: true,
          annotationSwitch: false,
          eraser: false))

      /// 右下角
      ..add(GestureRecording(
          data: Offset(
              imagInfoModel!.scaleWidth! - 4.w, trajectory.pictureQuestionTop + trajectory.pictureQuestionHeight),
          scopeBox: true,
          annotationSwitch: false,
          eraser: false));

    Future.delayed(Duration.zero, () {
      ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys);
    });
    if (lattices.isNotEmpty) {
      Map<int, List<Lattices>> map = new Map.fromIterable(lattices,
          key: (key) => key.stroke,
          value: (value) {
            return lattices.where((item) => item.stroke == value.stroke).toList()
              ..sort((a, b) => a.time.compareTo(b.time));
          });

      List<int> keys = map.keys.toList();
      for (var i = 0; i < keys.length; i++) {
        int theKey = keys[i];
        int? nextKey = i + 1 < keys.length ? keys[i + 1] : null;
        List<Lattices> strokesData = map[theKey]!;
        List<Lattices>? nextStrokesData = nextKey != null ? map[nextKey]! : null;

        List<GestureRecording> newTrajectoryData = strokesData.map((e) {
          double theX = e.x * imagInfoModel!.scale!;
          double theY = e.y * imagInfoModel!.scale! + spacingHeight;

          return GestureRecording(
              eraser: false, data: Offset(theX, theY), usageTime: e.time.toInt(), annotationSwitch: false);
        }).toList()
          ..add(GestureRecording(eraser: false, annotationSwitch: false));
        // 原始轨迹展示
        for (var j = 0; j < newTrajectoryData.length; j++) {
          GestureRecording theRecording = newTrajectoryData[j];
          GestureRecording? nextRecording = j + 1 < newTrajectoryData.length ? newTrajectoryData[j + 1] : null;

          if (nextRecording == null) {
            // 这个是此个笔画最后一个动作
            // 笔画最后一个动作是data 是null  用时 是null
            if (mounted) {
              trajectorys = List.from(trajectorys)..add(theRecording);
              ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys);
            }
          } else {
            var duration1 = Duration(milliseconds: theRecording.usageTime!);
            var duration2 = nextRecording.usageTime != null ? Duration(milliseconds: nextRecording.usageTime!) : null;
            var differenceInMilliseconds = 0;
            if (duration2 != null) differenceInMilliseconds = (duration2 - duration1).inMilliseconds;

            var zhixinCall = () async {
              if (mounted) {
                print('执行添加笔画${i},${j}');
                trajectorys = List.from(trajectorys)..add(theRecording);
                ref.read(jobDrawingTrajectoryProvider.notifier).setVal(trajectorys);
              }
              if (duration2 == null && nextStrokesData != null) {
                // 此时最后一个笔画完成了 停止时间是在下一个笔画开始时间之差
                Lattices minLattices = nextStrokesData.reduce((e1, e2) => e1.time < e2.time ? e1 : e2);
                differenceInMilliseconds =
                    (Duration(milliseconds: minLattices.time.toInt()) - duration1).inMilliseconds;
                await Future.delayed(Duration(milliseconds: differenceInMilliseconds)); // 一个笔画完成进行下一个笔画的等待时间
              }
            };
            await Future.delayed(Duration(milliseconds: differenceInMilliseconds));
            // 加 await 就是每一笔的停顿时间 ，不加就是每一笔不停顿
            zhixinCall();
            /**
              Timer t = Timer(Duration(milliseconds: differenceInMilliseconds), () {

              });
              if (delayedCalls == null) {
                delayedCalls = [];
              }
              delayedCalls?.add(t);
              
              Timer t = Timer(Duration(milliseconds: differenceInMilliseconds), () => zhixinCall());
              add(t); // 添加到这里 用于切换试题后销毁未执行的任务
              */
          }
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    List<GestureRecording> points = ref.watch(jobDrawingTrajectoryProvider);

    return Container(
      width: widget.boxWidth,
      height: widget.boxHeight,
      alignment: Alignment.center,
      child: CustomPaint(
        foregroundPainter: DrawingPainter(points: points),
        size: Size(widget.boxWidth, widget.boxHeight),
        child: RepaintBoundary(
          child: Container(
            constraints: BoxConstraints(minHeight: widget.boxHeight),
            child: $TheCachedNetworkImage(
              (context, imageProvider) {
                Image imageWidget = Image(image: imageProvider, fit: BoxFit.contain);

                if (imagInfoModel == null || widget.questionNumber != oldQuestionNumber) {
                  imageStream?.removeListener(theImageStreamListener);
                  // 视图中展示图片的尺寸计算获取
                  imageStream = imageWidget.image.resolve(ImageConfiguration());
                  imageStream?.addListener(theImageStreamListener);
                }

                return imageWidget;
              },
              imageUrl: widget.trajectory.paperPicture,
            ),
          ),
        ),
      ),
    );
  }
}

class DrawingPainter extends CustomPainter {
  List<GestureRecording> points;

  DrawingPainter({required this.points}) : super();

  Paint paintBrush = Paint()
    ..color = Colors.black
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 0.5.sp;

  /// 范围框
  Paint scopeBox = Paint()
    ..color = Colors.red
    ..strokeCap = StrokeCap.round
    ..strokeWidth = 1.2.sp;

  @override
  void paint(Canvas canvas, Size size) {
    if (points.length > 1) {
      if (points.length >= 4) {
        var sketchingFrame = points.take(4).where((e) => e.scopeBox && e.data != null).toList();
        if (sketchingFrame.length == 4) {
          var sketchingFramePoints = sketchingFrame.map((e) => e.data!).toList();

          // 假设points按照顺时针或逆时针方向给出了正方形的四个顶点
          canvas.drawLine(sketchingFramePoints[0], sketchingFramePoints[2], scopeBox);
          canvas.drawLine(sketchingFramePoints[0], sketchingFramePoints[1], scopeBox);
          canvas.drawLine(sketchingFramePoints[2], sketchingFramePoints[3], scopeBox);
          canvas.drawLine(sketchingFramePoints[1], sketchingFramePoints[3], scopeBox);
        }
        if (sketchingFrame.length > 0) {
          points = points.where((element) => !element.scopeBox).toList();
        }
      }
      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, paintBrush);
        }
      }
    }
  }

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

@hwidget
Widget $theCachedNetworkImage(ImageWidgetBuilder imageBuilder, {required String imageUrl}) {
  UseCachedImgRefresh _useImgRefsh = UseCachedImgRefresh.use();

  return CachedNetworkImage(
    key: _useImgRefsh.imageKey.value,
    fit: BoxFit.contain,
    imageUrl: imageUrl,
    imageBuilder: imageBuilder,
    placeholder: (context, url) => Center(child: SpinKitWave(color: Theme.of(context).primaryColor, size: 50.r)),
    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),
          ],
        ),
      );
    },
  );
}
