// 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.isCompleted) {
      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());
}
