import 'package:flutter/material.dart';
import 'package:flutter/animation.dart';

// // 사용 예시
// Container(
//   width: 64.w,
//   height: 64.w,
//   decoration: BoxDecoration(
//     color: staff.TRColors.SplashBackground,
//     borderRadius: BorderRadius.circular(180),
//   ),
//   child: JumpingDotsProgressIndicator(
//     dotSpacing: 8.w,
//     fontSize: 8.w,
//     color: TRColors.button_white,
//   ),
// ),

class _JumpingDot extends AnimatedWidget {
  final Color? color;
  final double? fontSize;

  const _JumpingDot(
      {Key? key,
      required Animation<double> animation,
      this.color,
      this.fontSize})
      : super(key: key, listenable: animation);

  Widget build(BuildContext context) {
    final Animation<double> animation = listenable as Animation<double>;
    return SizedBox(
      height: animation.value + fontSize!,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          // 사이즈 고정
          Container(
            width: fontSize!,
            height: fontSize!,
            decoration: BoxDecoration(
              color: color,
              borderRadius: BorderRadius.circular(50),
            ),
          ),
        ],
      ),
    );
  }
}

class JumpingDotsLoading extends StatefulWidget {
  /// 로딩 Dots 숫자 기본 = 3.
  final int numberOfDots;

  /// 사이즈
  final double fontSize;

  /// Dots 사이 공백, default 0.0.
  final double dotSpacing;

  /// Dots 색, default black.
  final Color color;

  /// Animation 시간, default 250 milliseconds.
  final int milliseconds;

  /// Animations 의 시작과 끝 크기.
  final double beginTweenValue;
  final double endTweenValue;

  final Curve animationCurve;

  /// Creates a jumping do progress indicator.
  JumpingDotsLoading({
    required this.fontSize,
    required this.dotSpacing,
    this.beginTweenValue = 0.0,
    this.endTweenValue = 30.0,
    this.animationCurve = Curves.easeInOut,
    this.numberOfDots = 3,
    this.color = Colors.black,
    this.milliseconds = 250,
  });

  _JumpingDotsLoadingState createState() => _JumpingDotsLoadingState(
        numberOfDots: this.numberOfDots,
        fontSize: this.fontSize,
        color: this.color,
        dotSpacing: this.dotSpacing,
        milliseconds: this.milliseconds,
      );
}

class _JumpingDotsLoadingState extends State<JumpingDotsLoading>
    with TickerProviderStateMixin {
  int? numberOfDots;
  int? milliseconds;
  double fontSize;
  double dotSpacing;
  Color? color;
  List<AnimationController> controllers = <AnimationController>[];
  List<Animation<double>> animations = <Animation<double>>[];
  List<Widget> _widgets = <Widget>[];

  _JumpingDotsLoadingState({
    this.numberOfDots,
    required this.fontSize,
    this.color,
    required this.dotSpacing,
    this.milliseconds,
  });

  @override
  initState() {
    super.initState();
    for (int i = 0; i < numberOfDots!; i++) {
      _addAnimationControllers();
      _buildAnimations(i);
      _addListOfDots(i);
    }

    controllers[0].forward();
  }

  @override
  dispose() {
    for (int i = 0; i < numberOfDots!; i++) controllers[i].dispose();
    super.dispose();
  }

  void _addAnimationControllers() {
    controllers.add(AnimationController(
        duration: Duration(milliseconds: milliseconds!), vsync: this));
  }

  void _addListOfDots(int index) {
    _widgets.add(
      Padding(
        padding: EdgeInsets.symmetric(horizontal: dotSpacing! / 2),
        child: _JumpingDot(
          animation: animations[index],
          fontSize: fontSize,
          color: color,
        ),
      ),
    );
  }

  void _buildAnimations(int index) {
    animations.add(
      Tween(begin: widget.beginTweenValue, end: widget.endTweenValue).animate(
          CurvedAnimation(
              parent: controllers[index], curve: widget.animationCurve))
        // .animate(controllers[index])
        ..addStatusListener(
          (AnimationStatus status) {
            if (status == AnimationStatus.completed)
              controllers[index].reverse();
            if (index == numberOfDots! - 1 &&
                status == AnimationStatus.dismissed) {
              controllers[0].forward();
            }
            if (animations[index].value > widget.endTweenValue / 2 &&
                index < numberOfDots! - 1) {
              controllers[index + 1].forward();
            }
          },
        ),
    );
  }

  Widget build(BuildContext context) {
    return SizedBox(
      height: fontSize,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: _widgets,
      ),
    );
  }
}