// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter/material.dart';

/// An example of [AnimationController] and [SlideTransition].

// Occupies the same width as the widest single digit used by AnimatedDigit.
//
// By stacking this widget behind AnimatedDigit's visible digit, we
// ensure that AnimatedWidget's width will not change when its value
// changes.  Typically digits like '8' or '9' are wider than '1'.  If
// an app arranges several AnimatedDigits in a centered Row, we don't
// want the Row to wiggle when the digits change because the overall
// width of the Row changes.
class _PlaceholderDigit extends StatelessWidget {
  const _PlaceholderDigit();

  @override
  Widget build(BuildContext context) {
    final TextStyle textStyle = Theme.of(context).textTheme.displayLarge!.copyWith(
      fontWeight: FontWeight.w500,
    );

    final Iterable<Widget> placeholderDigits = <int>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].map<Widget>(
      (int n) {
        return Text('$n', style: textStyle);
      },
    );

    return Opacity(
      opacity: 0,
      child: Stack(children: placeholderDigits.toList()),
    );
  }
}

// Displays a single digit [value].
//
// When the value changes the old value slides upwards and out of sight
// at the same as the new value slides into view.
class AnimatedDigit extends StatefulWidget {
  const AnimatedDigit({ super.key, required this.value });

  final int value;

  @override
  State<AnimatedDigit> createState() => _AnimatedDigitState();
}

class _AnimatedDigitState extends State<AnimatedDigit> with SingleTickerProviderStateMixin {
  static const Duration defaultDuration = Duration(milliseconds: 300);

  late final AnimationController controller;
  late int incomingValue;
  late int outgoingValue;
  List<int> pendingValues = <int>[]; // widget.value updates that occurred while the animation is underway
  Duration duration = defaultDuration;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      duration: duration,
      vsync: this,
    );
    controller.addStatusListener(handleAnimationCompleted);
    incomingValue = widget.value;
    outgoingValue = widget.value;
  }

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

  void handleAnimationCompleted(AnimationStatus status) {
    if (status == AnimationStatus.completed) {
      if (pendingValues.isNotEmpty) {
        // Display the next pending value. The duration was scaled down
        // in didUpdateWidget by the total number of pending values so
        // that all of the pending changes are shown within
        // defaultDuration of the last one (the past pending change).
        controller.duration = duration;
        animateValueUpdate(incomingValue, pendingValues.removeAt(0));
      } else {
        controller.duration = defaultDuration;
      }
    }
  }

  void animateValueUpdate(int outgoing, int incoming) {
    setState(() {
      outgoingValue = outgoing;
      incomingValue = incoming;
      controller.forward(from: 0);
    });
  }

  // Rebuilding the widget with a new value causes the animations to run.
  // If the widget is updated while the value is being changed the new
  // value is added to pendingValues and is taken care of when the current
  // animation is complete (see handleAnimationCompleted()).
  @override
  void didUpdateWidget(AnimatedDigit oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.value != oldWidget.value) {
      if (controller.isAnimating) {
        // We're in the middle of animating outgoingValue out and
        // incomingValue in. Shorten the duration of the current
        // animation as well as the duration for animations that
        // will show the pending values.
        pendingValues.add(widget.value);
        final double percentRemaining = 1 - controller.value;
        duration = defaultDuration * (1 / (percentRemaining + pendingValues.length));
        controller.animateTo(1.0, duration: duration * percentRemaining);
      } else {
        animateValueUpdate(incomingValue, widget.value);
      }
    }
  }

  // When the controller runs forward both SlideTransitions' children
  // animate upwards. This takes the outgoingValue out of sight and the
  // incoming value into view. See animateValueUpdate().
  @override
  Widget build(BuildContext context) {
    final TextStyle textStyle = Theme.of(context).textTheme.displayLarge!;
    return ClipRect(
      child: Stack(
        children: <Widget>[
          const _PlaceholderDigit(),
          SlideTransition(
            position: controller
              .drive(
                Tween<Offset>(
                  begin: Offset.zero,
                  end: const Offset(0, -1), // Out of view above the top.
                ),
              ),
            child: Text(
              key: ValueKey<int>(outgoingValue),
              '$outgoingValue',
              style: textStyle,
            ),
          ),
          SlideTransition(
            position: controller
              .drive(
                Tween<Offset>(
                  begin: const Offset(0, 1), // Out of view below the bottom.
                  end: Offset.zero,
                ),
              ),
            child: Text(
              key: ValueKey<int>(incomingValue),
              '$incomingValue',
              style: textStyle,
            ),
          ),
        ],
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'AnimatedDigit',
      home: AnimatedDigitHome(),
    );
  }
}

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

  @override
  State<AnimatedDigitHome> createState() => _AnimatedDigitHomeState();
}

class _AnimatedDigitHomeState extends State<AnimatedDigitHome> {
  int value = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedDigit(value: value % 10),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() { value += 1; });
        },
        tooltip: 'Increment Digit',
        child: const Icon(Icons.add),
      ),
    );
  }
}

void main() {
  runApp(const AnimatedDigitApp());
}
