// 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 'tween.dart';

export 'tween.dart' show Animatable;

// Examples can assume:
// late AnimationController myAnimationController;

/// Enables creating an [Animation] whose value is defined by a sequence of
/// [Tween]s.
///
/// Each [TweenSequenceItem] has a weight that defines its percentage of the
/// animation's duration. Each tween defines the animation's value during the
/// interval indicated by its weight.
///
/// {@tool snippet}
/// This example defines an animation that uses an easing curve to interpolate
/// between 5.0 and 10.0 during the first 40% of the animation, remains at 10.0
/// for the next 20%, and then returns to 5.0 for the final 40%.
///
/// ```dart
/// final Animation<double> animation = TweenSequence<double>(
///   <TweenSequenceItem<double>>[
///     TweenSequenceItem<double>(
///       tween: Tween<double>(begin: 5.0, end: 10.0)
///         .chain(CurveTween(curve: Curves.ease)),
///       weight: 40.0,
///     ),
///     TweenSequenceItem<double>(
///       tween: ConstantTween<double>(10.0),
///       weight: 20.0,
///     ),
///     TweenSequenceItem<double>(
///       tween: Tween<double>(begin: 10.0, end: 5.0)
///         .chain(CurveTween(curve: Curves.ease)),
///       weight: 40.0,
///     ),
///   ],
/// ).animate(myAnimationController);
/// ```
/// {@end-tool}
class TweenSequence<T> extends Animatable<T> {
  /// Construct a TweenSequence.
  ///
  /// The [items] parameter must be a list of one or more [TweenSequenceItem]s.
  ///
  /// There's a small cost associated with building a [TweenSequence] so it's
  /// best to reuse one, rather than rebuilding it on every frame, when that's
  /// possible.
  TweenSequence(List<TweenSequenceItem<T>> items)
      : assert(items != null),
        assert(items.isNotEmpty) {
    _items.addAll(items);

    double totalWeight = 0.0;
    for (final TweenSequenceItem<T> item in _items) {
      totalWeight += item.weight;
    }
    assert(totalWeight > 0.0);

    double start = 0.0;
    for (int i = 0; i < _items.length; i += 1) {
      final double end = i == _items.length - 1 ? 1.0 : start + _items[i].weight / totalWeight;
      _intervals.add(_Interval(start, end));
      start = end;
    }
  }

  final List<TweenSequenceItem<T>> _items = <TweenSequenceItem<T>>[];
  final List<_Interval> _intervals = <_Interval>[];

  T _evaluateAt(double t, int index) {
    final TweenSequenceItem<T> element = _items[index];
    final double tInterval = _intervals[index].value(t);
    return element.tween.transform(tInterval);
  }

  @override
  T transform(double t) {
    assert(t >= 0.0 && t <= 1.0);
    if (t == 1.0) {
      return _evaluateAt(t, _items.length - 1);
    }
    for (int index = 0; index < _items.length; index++) {
      if (_intervals[index].contains(t)) {
        return _evaluateAt(t, index);
      }
    }
    // Should be unreachable.
    throw StateError('TweenSequence.evaluate() could not find an interval for $t');
  }

  @override
  String toString() => 'TweenSequence(${_items.length} items)';
}

/// Enables creating a flipped [Animation] whose value is defined by a sequence
/// of [Tween]s.
///
/// This creates a [TweenSequence] that evaluates to a result that flips the
/// tween both horizontally and vertically.
///
/// This tween sequence assumes that the evaluated result has to be a double
/// between 0.0 and 1.0.
class FlippedTweenSequence extends TweenSequence<double> {
  /// Creates a flipped [TweenSequence].
  ///
  /// The [items] parameter must be a list of one or more [TweenSequenceItem]s.
  ///
  /// There's a small cost associated with building a `TweenSequence` so it's
  /// best to reuse one, rather than rebuilding it on every frame, when that's
  /// possible.
  FlippedTweenSequence(super.items)
    : assert(items != null);

  @override
  double transform(double t) => 1 - super.transform(1 - t);
}

/// A simple holder for one element of a [TweenSequence].
class TweenSequenceItem<T> {
  /// Construct a TweenSequenceItem.
  ///
  /// The [tween] must not be null and [weight] must be greater than 0.0.
  const TweenSequenceItem({
    required this.tween,
    required this.weight,
  }) : assert(tween != null),
       assert(weight != null),
       assert(weight > 0.0);

  /// Defines the value of the [TweenSequence] for the interval within the
  /// animation's duration indicated by [weight] and this item's position
  /// in the list of items.
  ///
  /// {@tool snippet}
  ///
  /// The value of this item can be "curved" by chaining it to a [CurveTween].
  /// For example to create a tween that eases from 0.0 to 10.0:
  ///
  /// ```dart
  /// Tween<double>(begin: 0.0, end: 10.0)
  ///   .chain(CurveTween(curve: Curves.ease))
  /// ```
  /// {@end-tool}
  final Animatable<T> tween;

  /// An arbitrary value that indicates the relative percentage of a
  /// [TweenSequence] animation's duration when [tween] will be used.
  ///
  /// The percentage for an individual item is the item's weight divided by the
  /// sum of all of the items' weights.
  final double weight;
}

class _Interval {
  const _Interval(this.start, this.end) : assert(end > start);

  final double start;
  final double end;

  bool contains(double t) => t >= start && t < end;

  double value(double t) => (t - start) / (end - start);

  @override
  String toString() => '<$start, $end>';
}
