import 'dart:math';

import 'dart:ui' as ui;

import 'package:dash_painter/dash_painter.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';

/// create by 张风捷特烈 on 2020/11/5
/// contact me by email 1981462002@qq.com
/// 说明:

class Paper extends StatefulWidget {
  const Paper({Key? key}) : super(key: key);

  @override
  State<Paper> createState() => _PaperState();
}

class _PaperState extends State<Paper>
    with SingleTickerProviderStateMixin {
  Line line = Line(start: const Offset(20, 20), end: const Offset(50, 80));

  late AnimationController ctrl;

  @override
  void initState() {
    super.initState();
    ctrl = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 3),
    )..addListener(_updateLine);
  }

  @override
  void dispose() {
    line.dispose();
    ctrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {

    return Center(
      child: GestureDetector(
        onTap: () {
          // line.record();
          ctrl.forward(from: 0);
        },
        child: CustomPaint(
          painter: AnglePainter(line: line
            // linker: linker
          ),
          child: Container(
            color: Colors.grey.withOpacity(0.1),
            height: 200,
            width: 200,
          ),
        ),
      ),
    );
  }

  void _updateLine() {
    // print("${ctrl.value * 2 * pi}");
    Offset center = line.percent(0.2);
    line.rotate(ctrl.value * 2 * pi, centre: center);
    // line.rotate(ctrl.value * 2* pi);
  }
}

class AnglePainter extends CustomPainter {
  final DashPainter dashPainter = const DashPainter(span: 4, step: 4);

  AnglePainter({required this.line}) : super(repaint: line);

  final Paint pointPaint = Paint()
    ..style = PaintingStyle.stroke
    ..strokeWidth = 1;

  final Paint helpPaint = Paint()
    ..style = PaintingStyle.stroke
    ..color = Colors.lightBlue
    ..strokeWidth = 1;

  final TextPainter textPainter = TextPainter(
    textAlign: TextAlign.center,
    textDirection: TextDirection.ltr,
  );

  final Line line;

  @override
  void paint(Canvas canvas, Size size) {
    canvas.translate(size.width / 2, size.height / 2);
    drawHelp(canvas, size);
    line.paint(canvas);
  }

  void drawHelp(Canvas canvas, Size size) {
    Path helpPath = Path()
      ..moveTo(-size.width / 2, 0)
      ..relativeLineTo(size.width, 0)
      ..moveTo(0, -size.height / 2)
      ..relativeLineTo(0, size.height);
    dashPainter.paint(canvas, helpPath, helpPaint);

    drawHelpText('0°', canvas, Offset(size.width / 2 - 20, 0));
    drawHelpText('p0', canvas, line.start.translate(-20, 0));
    drawHelpText('p1', canvas, line.end.translate(-20, 0));

    // drawHelpText('p2', canvas, Offset(60, 40).translate(10, 0));
    // drawAnchor(canvas, Offset(60, 40));
    drawAnchor(canvas, line.percent(0.2));
    // drawAnchor(canvas, line.percent(0.5));

    // drawAnchor(canvas, line.percent(0.8));

    drawHelpText(
      '角度: ${(line.positiveRad * 180 / pi).toStringAsFixed(2)}°',
      canvas,
      Offset(
        -size.width / 2 + 10,
        -size.height / 2 + 10,
      ),
    );



    // canvas.drawArc(
    //   Rect.fromCenter(center: line.start, width: 20, height: 20),
    //   0,
    //   line.positiveRad,
    //   false,
    //   helpPaint,
    // );

    // canvas.save();
    // Offset center = const Offset(60, 60);
    // canvas.translate(center.dx, center.dy);
    // canvas.rotate(line.positiveRad);
    // canvas.translate(-center.dx, -center.dy);
    // canvas.drawCircle(center, 4, helpPaint);
    // canvas.drawRect(
    //     Rect.fromCenter(center: center, width: 30, height: 60), helpPaint);
    // canvas.restore();
  }

  void drawAnchor(Canvas canvas, Offset offset) {
    canvas.drawCircle(offset, 4, pointPaint..style = PaintingStyle.stroke);
    canvas.drawCircle(offset, 2, pointPaint..style = PaintingStyle.fill);
  }

  void drawHelpText(
      String text,
      Canvas canvas,
      Offset offset, {
        Color color = Colors.lightBlue,
      }) {
    textPainter.text = TextSpan(
      text: text,
      style: TextStyle(fontSize: 12, color: color),
    );
    textPainter.layout(maxWidth: 200);
    textPainter.paint(canvas, offset);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

class Line with ChangeNotifier {
  Line({
    this.start = Offset.zero,
    this.end = Offset.zero,
  });

  Offset start;
  Offset end;

  final Paint pointPaint = Paint()
    ..style = PaintingStyle.stroke
    ..strokeWidth = 1;

  void paint(Canvas canvas) {
    canvas.drawLine(start, end, pointPaint);
    drawAnchor(canvas, start);
    drawAnchor(canvas, end);
  }

  double get rad => (end - start).direction;

  double get positiveRad => rad < 0 ? 2 * pi + rad : rad;

  double get length => (end - start).distance;

  void drawAnchor(Canvas canvas, Offset offset) {
    canvas.drawCircle(offset, 4, pointPaint..style = PaintingStyle.stroke);
    canvas.drawCircle(offset, 2, pointPaint..style = PaintingStyle.fill);
  }

  double detaRotate = 0;

  void rotate(double rotate, {Offset? centre}) {
    detaRotate = rotate - detaRotate;
    centre = centre ?? start;
    Line p2p0 = Line(start: centre, end: start);
    Line p2p1 = Line(start: centre, end: end);
    p2p0._rotateByStart(detaRotate);
    p2p1._rotateByStart(detaRotate);
    start = p2p0.end;
    end = p2p1.end;
    detaRotate = rotate;
    notifyListeners();
  }



  Offset percent(double percent){
    return Offset(
      length*percent*cos(rad),
      length*percent*sin(rad),
    )+start;
  }

  void _rotateByStart(double rotate) {
    end = Offset(
      length * cos(rad + rotate),
      length * sin(rad + rotate),
    ) +
        start;
  }

  void tick() {
    notifyListeners();
  }
}