import 'dart:math';
import 'dart:ui';

// import 'dart:ui' as ui;
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

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

class Paper extends StatelessWidget {
  const Paper({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      alignment: Alignment.center,
      child: const ICharts(),
    );
  }
}


class ICharts extends StatefulWidget {
  const ICharts({super.key});

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

class _IChartsState extends State<ICharts> with SingleTickerProviderStateMixin {
  late AnimationController _controller;

  @override
  void initState() {
    super.initState();
    _controller = AnimationController(
      duration: const Duration(milliseconds: 1500),
      vsync: this,
    )
      ..forward();
  }

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

  @override
  Widget build(BuildContext context) {
    return Stack(alignment: Alignment.topCenter, children: [
      Container(
        width: 500,
        height: 380,
        padding: EdgeInsets.only(top: 20, right: 20, bottom: 20, left: 20),
        child: CustomPaint(
          painter: ChartPainter(repaint: _controller),
        ),
      ),
      // Padding(
      //   padding: const EdgeInsets.only(top: 8.0),
      //   child: Text(
      //     "捷特 3 月支出统计图 - 2040 年",
      //     style: TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
      //   ),
      // )
    ]);
  }
}

const double _kPiePadding = 20; // 圆边距
const double _kStrokeWidth = 12; // 圆弧宽
const double _kAngle = 270; // 圆弧角度
const int _kMax = 220; // 最大刻度值
const int _kMin = 0; // 最小刻度值
const double _kColorStopRate = 0.2; // 颜色变化分率
const double _kScaleHeightLever1 = 14; // 短刻度线
const double _kScaleHeightLever2 = 18; // 逢5线
const double _kScaleHeightLever3 = 20; // 逢10线
const double _kScaleDensity = 0.5; // 密度
const double _kScaleTextStep = 10; // 刻度文字步长

const List<Color> _kColors = [
  // 颜色列表
  Colors.green,
  Colors.blue,
  Colors.red,
];

class ChartPainter extends CustomPainter {
  final TextPainter _textPainter =
  TextPainter(textDirection: TextDirection.ltr);

  double value = 150; //指针数值
  double radius = 0; // 圆半径

  final Animation<double> repaint;

  Paint fillPaint = Paint();

  Paint stokePaint = Paint()
    ..strokeWidth = 1
    ..style = PaintingStyle.stroke;

  double get initAngle => (360 - _kAngle) / 2;

  ChartPainter({required this.repaint}) : super(repaint: repaint);

  @override
  void paint(Canvas canvas, Size size) {
    radius = size.shortestSide / 2 - _kPiePadding; // 当前圆半径
    canvas.translate(size.width / 2, size.height / 2); // 画布原点移至中点

    drawText(canvas);
    drawArrow(canvas); // 绘制指针
    canvas.rotate(pi / 2); // 将起始点旋转到 y 轴正方向
    drawScale(canvas); // 绘制刻度
    drawOutline(canvas); // 绘制弧线
  }

  void drawOutline(Canvas canvas) {
    Path path = Path()..moveTo(radius, 0);
    path.arcTo(
        Rect.fromCenter(
            center: Offset.zero, width: radius * 2, height: radius * 2),
        pi / 180 * initAngle,
        pi / 180 * _kAngle,
        true);

    PathMetrics pms = path.computeMetrics();
    stokePaint..strokeWidth = _kStrokeWidth;
    pms.forEach((PathMetric pm) {
      canvas.drawPath(pm.extractPath(0, pm.length * _kColorStopRate),
          stokePaint..color = _kColors[0]);
      canvas.drawPath(
          pm.extractPath(
              pm.length * _kColorStopRate, pm.length * (1 - _kColorStopRate)),
          stokePaint..color = _kColors[1]);
      canvas.drawPath(
          pm.extractPath(pm.length * (1 - _kColorStopRate), pm.length),
          stokePaint..color = _kColors[2]);
    });
  }

  void drawScale(Canvas canvas) {
    canvas.save();
    canvas.rotate(pi / 180 * initAngle);
    double len = 0;
    Color color = Colors.red;
    int count = (_kMax * _kScaleDensity).toInt(); // 格线个数
    for (int i = _kMin; i <= count; i++) {
      if (i % 5 == 0 && i % 10 != 0) {
        len = _kScaleHeightLever2;
      } else if (i % 10 == 0) {
        len = _kScaleHeightLever3;
      } else {
        len = _kScaleHeightLever1;
      }
      if (i < count * _kColorStopRate) {
        color = Colors.green;
      } else if (i < count * (1 - _kColorStopRate)) {
        color = Colors.blue;
      } else {
        color = Colors.red;
      }
      canvas.drawLine(Offset(radius + _kStrokeWidth / 2, 0),
          Offset(radius - len, 0), stokePaint..color = color..strokeWidth=1);
      canvas.rotate(pi / 180 / _kMax * _kAngle / _kScaleDensity);
    }
    canvas.restore();
  }

  void drawArrow(Canvas canvas) {
    var nowPer = value / _kMax;
    Color color = Colors.red;
    canvas.save();
    double radians = pi / 180 * (-_kAngle / 2 + nowPer * _kAngle*repaint.value);
    canvas.rotate(radians);
    Path arrowPath = Path();
    arrowPath.moveTo(0, 18);
    arrowPath.relativeLineTo(-6, -10);
    arrowPath.relativeLineTo(6, -radius + 10);
    arrowPath.relativeLineTo(6, radius - 10);
    arrowPath.close();

    if (nowPer < _kColorStopRate) {
      color = _kColors[0];
    } else if (nowPer < (1 - _kColorStopRate)) {
      color = _kColors[1];
    } else {
      color = _kColors[2];
    }

    canvas.drawPath(arrowPath, fillPaint..color = color);
    canvas.drawCircle(Offset.zero, 3, stokePaint..color = Colors.yellow..strokeWidth=1);
    canvas.drawCircle(Offset.zero, 3, fillPaint..color = Colors.white);
    canvas.restore();
  }

  void drawText(Canvas canvas) {
    _drawAxisText(canvas, 'km/s',
        fontSize: 20,
        fontStyle: FontStyle.italic,
        fontWeight: FontWeight.bold,
        alignment: Alignment.center,
        color: Colors.black,
        offset: Offset(0, -radius / 2));

    _drawAxisText(canvas, '${value.toStringAsFixed(1)}',
        fontSize: 16,
        alignment: Alignment.center,
        color: Colors.black,
        offset: Offset(0, radius / 2));

    int count = (_kMax - _kMin) * _kScaleDensity ~/ _kScaleTextStep;
    Color color = Colors.red;
    for (int i = _kMin; i <= count; i++) {
      var thta = pi / 180 * (90 + initAngle + (_kAngle / count) * i);
      if (i < count * _kColorStopRate) {
        color = _kColors[0];
      } else if (i < count * (1 - _kColorStopRate)) {
        color = _kColors[1];
      } else {
        color = _kColors[2];
      }

      Rect rect = Rect.fromLTWH((radius - 40) * cos(thta) - 12,
          (radius - 40) * sin(thta) - 8, 24, 16);

      canvas.drawRRect(RRect.fromRectAndRadius(rect, Radius.circular(3)),
          fillPaint..color = color);
      _drawAxisText(canvas, '${i * _kScaleTextStep ~/ _kScaleDensity}',
          fontSize: 11,
          alignment: Alignment.center,
          color: Colors.white,
          offset: Offset((radius - 40) * cos(thta), (radius - 40) * sin(thta)));
    }
  }

  void _drawAxisText(Canvas canvas, String str,
      {Color color = Colors.black,
        double fontSize = 11,
        FontStyle fontStyle = FontStyle.normal,
        Alignment alignment = Alignment.centerRight,
        FontWeight fontWeight = FontWeight.normal,
        Offset offset = Offset.zero}) {
    TextSpan text = TextSpan(
        text: str,
        style: TextStyle(
          fontSize: fontSize,
          fontWeight: fontWeight,
          fontStyle: fontStyle,
          color: color,
        ));

    _textPainter.text = text;
    _textPainter.layout(); // 进行布局

    Size size = _textPainter.size;

    Offset offsetPos = Offset(-size.width / 2, -size.height / 2)
        .translate(-size.width / 2 * alignment.x + offset.dx, 0.0 + offset.dy);
    _textPainter.paint(canvas, offsetPos);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
