import 'dart:math';

import 'package:flutter/material.dart';
import 'package:sport/application.dart';

class WavePainter extends CustomPainter {
  int waveCount;
  int crestCount;
  double waveHeight;
  List<Color> waveColors;
  double circleWidth;
  Color circleColor;
  Color circleBackgroundColor;
  bool showProgressText;
  TextStyle textStyle;

  Animation<double> _xAnimation;
  Animation<double> _yAnimation;

  set XAnimation(Animation<double> value) {
    _xAnimation = value;
  }

  set YAnimation(Animation<double> value) {
    _yAnimation = value;
  }

  Animation<double> get YAnimation => _yAnimation;

  Animation<double> get XAnimation => _xAnimation;

  WavePainter(
      {this.waveCount = 1,
      this.crestCount = 2,
      this.waveHeight,
      this.waveColors,
      this.circleColor = Colors.grey,
      this.circleBackgroundColor = Colors.white,
      this.circleWidth = 5.0,
      this.showProgressText = false,
      this.textStyle = const TextStyle(
        fontSize: 60.0,
        color: Colors.blue,
        fontWeight: FontWeight.bold,
        shadows: [Shadow(color: Colors.grey, offset: Offset(5.0, 5.0), blurRadius: 5.0)],
      )});

  @override
  void paint(Canvas canvas, Size size) {
    double width = size.width;
    double height = size.height;

    if (waveHeight == null) {
      waveHeight = height / 8;
      height = height + waveHeight;
    }

    if (waveColors == null) {
      waveColors = [Color.fromARGB(100, Colors.blue.red, Colors.blue.green, Colors.blue.blue)];
    }

    Offset center = new Offset(width / 2, height / 2);
    double xMove = width * XAnimation.value;
    double yAnimValue = 0.0;
    if (YAnimation != null) {
      yAnimValue = YAnimation.value;
    }
    double yMove = height * (1.0 - yAnimValue);
    Offset waveCenter = new Offset(xMove, yMove);

    var paintCircle = new Paint()
      ..color = Colors.grey
      ..style = PaintingStyle.fill
      ..strokeWidth = circleWidth
      ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);

    canvas.drawCircle(center, min(width, height) / 2, paintCircle);

    List<Path> wavePaths = [];

    for (int index = 0; index < waveCount; index++) {
      double direction = pow(-1.0, index);
      Path path = new Path()
        ..moveTo(waveCenter.dx - width, waveCenter.dy)
        ..lineTo(waveCenter.dx - width, center.dy + height / 2)
        ..lineTo(waveCenter.dx + width, center.dy + height / 2)
        ..lineTo(waveCenter.dx + width, waveCenter.dy);

      for (int i = 0; i < 2; i++) {
        for (int j = 0; j < crestCount; j++) {
          double a = pow(-1.0, j);
          path
            ..quadraticBezierTo(waveCenter.dx + width * (1 - i - (1 + 2 * j) / (2 * crestCount)), waveCenter.dy + waveHeight * a * direction,
                waveCenter.dx + width * (1 - i - (2 + 2 * j) / (2 * crestCount)), waveCenter.dy);
        }
      }

      path..close();

      wavePaths.add(path);
    }

    var paint = new Paint()
      ..color = circleBackgroundColor
      ..style = PaintingStyle.fill
      ..maskFilter = MaskFilter.blur(BlurStyle.inner, 5.0);

    canvas.saveLayer(Rect.fromCircle(center: center, radius: min(width, height) / 2), paint);

    canvas.drawCircle(center, min(width, height) / 2, paint);

    Rect rect = Rect.fromLTRB(0, 0, size.width, 180);
    paint
      ..blendMode = BlendMode.srcATop
      ..style = PaintingStyle.fill
      ..strokeWidth = 2.0
      ..maskFilter = MaskFilter.blur(BlurStyle.inner, 10.0);

    for (int i = 0; i < wavePaths.length; i++) {
      if (waveColors.length >= wavePaths.length) {
        if (i == 0) {
          paint.shader = LinearGradient(
            begin: Alignment.bottomCenter,
            end: Alignment.topCenter,
            colors: <Color>[Color(0xffFF7700), Color(0x44FFD014)],
          ).createShader(rect);
        } else {
          paint.shader = LinearGradient(
            begin: Alignment.bottomCenter,
            end: Alignment.topCenter,
            colors: <Color>[Color(0x99FF7700), Color(0x99FFD014)],
          ).createShader(rect);
        }
      } else {
        paint.shader = LinearGradient(
          begin: Alignment.bottomCenter,
          end: Alignment.topCenter,
          colors: <Color>[Color(0xffFFE600), Color(0xffFF9100)],
        ).createShader(rect);
      }

      canvas.drawPath(wavePaths[i], paint);
    }

//    paint.blendMode = BlendMode.srcATop;
    if (showProgressText) {
      TextPainter tp = TextPainter(text: TextSpan(text: '${(yAnimValue * 100.0).toStringAsFixed(0)}%', style: textStyle), textDirection: TextDirection.rtl)
        ..layout();

      tp.paint(canvas, Offset(center.dx - tp.width / 2, center.dy - tp.height / 2));
    }
    canvas.restore();

  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return oldDelegate != this;
  }
}

class ProgressManager extends StatefulWidget {

  final double progress;

  ProgressManager(this.progress);

  @override
  _ProgressManagerState createState() => new _ProgressManagerState()
    .._factory = WavePainter(
        waveCount: 2,
        waveColors: [
          Color.fromARGB(100, Colors.pink.red, Colors.pink.green, Colors.pink.blue),
          Color.fromARGB(150, Colors.pink.red, Colors.pink.green, Colors.pink.blue),
        ],
        circleBackgroundColor: Color(0xffffffff),
        circleWidth: 2.0);
}

class _ProgressManagerState extends State<ProgressManager> with TickerProviderStateMixin {
  AnimationController xController;
  AnimationController yController;
  Animation<double> xAnimation;
  Animation<double> yAnimation;
  List<double> _progressList = [];
  double curProgress = 0;
  WavePainter _factory;

  set painter(WavePainter factory) {
    _factory = factory;
  }

  setProgress(double progress) {
    _progressList.add(progress);
    onProgressChange();
  }

  onProgressChange() {
    if (yController == null) return;

    if (_progressList.length > 0) {
      if (yController != null && yController.isAnimating) {
        return;
      }
      double nextProgress = _progressList[0];
      _progressList.removeAt(0);
      final double begin = curProgress;
      yController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
      yAnimation = AlwaysStoppedAnimation(widget.progress);
      yAnimation.addListener(_onProgressChange);
      yAnimation.addStatusListener(_onProgressStatusChange);
      yController.forward();
    }
  }

  @override
  void initState() {
    super.initState();
    xController = new AnimationController(vsync: this, duration: Duration(milliseconds: 3000));
    xAnimation = new Tween(begin: 0.0, end: 1.0).animate(xController);

    xAnimation.addListener(_change);
//    xAnimation.addStatusListener((status) {
//      if (status == AnimationStatus.completed) {
//        xController.reverse();
//      } else if (status == AnimationStatus.dismissed) {
//        xController.forward();
//      }
//    });

//    yController = new AnimationController(
//        vsync: this, duration: Duration(milliseconds: 500));
    yAnimation = AlwaysStoppedAnimation(widget.progress);
//    yAnimation.addListener(_onProgressChange);
//    yAnimation.addStatusListener(_onProgressStatusChange);

    doDelay(xController, 0);
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: double.infinity,
      height: double.infinity,
      child: CustomPaint(
        painter: _factory
          ..XAnimation = xAnimation
          ..YAnimation = AlwaysStoppedAnimation(widget.progress),
        child: Container(
          child: Text(
            "${xAnimation.value}",
            style: TextStyle(color: Colors.transparent),
          ),
        ),
      ),
    );
  }

  void _change() {
    if(Application.currentPage == 0) {
   // print("222222222 ${xAnimation.value}");
   // print("${Application.currentPage}");
    setProgress(xAnimation.value);
    setState(() {});
    }
  }

  void _onProgressChange() {
      setState(() {
        //      curProgress = yAnimation.value;
      });
  }

  void _onProgressStatusChange(status) {
    if (status == AnimationStatus.completed) {
      onProgressChange();
    }
  }

  void doDelay(AnimationController controller, int delay) async {
    Future.delayed(Duration(milliseconds: delay), () {
      controller..repeat();
    });
  }

  @override
  void dispose() {
    xController.dispose();
    if (yController != null) yController.dispose();
    xAnimation.removeListener(_change);
    yAnimation.removeListener(_onProgressChange);
    yAnimation.removeStatusListener(_onProgressStatusChange);
    super.dispose();
  }
}
