// 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.

// @dart = 2.8

import 'dart:math' as math;

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'scaffold.dart';

/// The margin that a [FloatingActionButton] should leave between it and the
/// edge of the screen.
///
/// [FloatingActionButtonLocation.endFloat] uses this to set the appropriate margin
/// between the [FloatingActionButton] and the end of the screen.
const double kFloatingActionButtonMargin = 16.0;

/// The amount of time the [FloatingActionButton] takes to transition in or out.
///
/// The [Scaffold] uses this to set the duration of [FloatingActionButton]
/// motion, entrance, and exit animations.
const Duration kFloatingActionButtonSegue = Duration(milliseconds: 200);

/// The fraction of a circle the [FloatingActionButton] should turn when it enters.
///
/// Its value corresponds to 0.125 of a full circle, equivalent to 45 degrees or pi/4 radians.
const double kFloatingActionButtonTurnInterval = 0.125;

/// If a [FloatingActionButton] is used on a [Scaffold] in certain positions,
/// it is moved [kMiniButtonOffsetAdjustment] pixels closer to the edge of the screen.
///
/// This is intended to be used with [FloatingActionButton.mini] set to true,
/// so that the floating action button appears to align with [CircleAvatar]s
/// in the [ListTile.leading] slot of a [ListTile] in a [ListView] in the
/// [Scaffold.body].
///
/// More specifically:
/// * In the following positions, the [FloatingActionButton] is moved *horizontally*
/// closer to the edge of the screen:
///   * [FloatingActionButtonLocation.miniStartTop]
///   * [FloatingActionButtonLocation.miniStartFloat]
///   * [FloatingActionButtonLocation.miniStartDocked]
///   * [FloatingActionButtonLocation.miniEndTop]
///   * [FloatingActionButtonLocation.miniEndFloat]
///   * [FloatingActionButtonLocation.miniEndDocked]
/// * In the following positions, the [FloatingActionButton] is moved *vertically*
/// closer to the bottom of the screen:
///   * [FloatingActionButtonLocation.miniStartFloat]
///   * [FloatingActionButtonLocation.miniCenterFloat]
///   * [FloatingActionButtonLocation.miniEndFloat]
const double kMiniButtonOffsetAdjustment = 4.0;

/// An object that defines a position for the [FloatingActionButton]
/// based on the [Scaffold]'s [ScaffoldPrelayoutGeometry].
///
/// Flutter provides [FloatingActionButtonLocation]s for the common
/// [FloatingActionButton] placements in Material Design applications. These
/// locations are available as static members of this class.
///
/// See also:
///
///  * [FloatingActionButton], which is a circular button typically shown in the
///    bottom right corner of the app.
///  * [FloatingActionButtonAnimator], which is used to animate the
///    [Scaffold.floatingActionButton] from one [FloatingActionButtonLocation] to
///    another.
///  * [ScaffoldPrelayoutGeometry], the geometry that
///    [FloatingActionButtonLocation]s use to position the [FloatingActionButton].
abstract class FloatingActionButtonLocation {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const FloatingActionButtonLocation();

  /// Start-aligned [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body].
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.leading] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniStartTop] and set [FloatingActionButton.mini] to true.
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation startTop = _StartTopFabLocation();

  /// Start-aligned [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body], optimized for mini floating
  /// action buttons.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.leading] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation miniStartTop = _MiniStartTopFabLocation();

  /// Centered [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body].
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation centerTop = _CenterTopFabLocation();

  /// Centered [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body], intended to be used with
  /// [FloatingActionButton.mini] set to true.
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation miniCenterTop = _MiniCenterTopFabLocation();

  /// End-aligned [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body].
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.trailing] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniEndTop] and set [FloatingActionButton.mini] to true.
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation endTop = _EndTopFabLocation();

  /// End-aligned [FloatingActionButton], floating over the transition between
  /// the [Scaffold.appBar] and the [Scaffold.body], optimized for mini floating
  /// action buttons.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.trailing] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// This is unlikely to be a useful location for apps that lack a top [AppBar]
  /// or that use a [SliverAppBar] in the scaffold body itself.
  static const FloatingActionButtonLocation miniEndTop = _MiniEndTopFabLocation();

  /// Start-aligned [FloatingActionButton], floating at the bottom of the screen.
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.leading] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniStartFloat] and set [FloatingActionButton.mini] to true.
  static const FloatingActionButtonLocation startFloat = _StartFloatFabLocation();

  /// Start-aligned [FloatingActionButton], floating at the bottom of the screen,
  /// optimized for mini floating action buttons.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.leading] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// Compared to [FloatingActionButtonLocation.startFloat], floating action
  /// buttons using this location will move horizontally _and_ vertically
  /// closer to the edges, by [kMiniButtonOffsetAdjustment] each.
  static const FloatingActionButtonLocation miniStartFloat = _MiniStartFloatFabLocation();

  /// Centered [FloatingActionButton], floating at the bottom of the screen.
  ///
  /// To position a mini floating action button, use [miniCenterFloat] and
  /// set [FloatingActionButtonLocation.mini] to true.
  static const FloatingActionButtonLocation centerFloat = _CenterFloatFabLocation();

  /// Centered [FloatingActionButton], floating at the bottom of the screen,
  /// optimized for mini floating action buttons.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align horizontally with
  /// the locations [FloatingActionButtonLocation.miniStartFloat]
  /// and [FloatingActionButtonLocation.miniEndFloat].
  ///
  /// Compared to [FloatingActionButtonLocation.centerFloat], floating action
  /// buttons using this location will move vertically down
  /// by [kMiniButtonOffsetAdjustment].
  static const FloatingActionButtonLocation miniCenterFloat = _MiniCenterFloatFabLocation();

  /// End-aligned [FloatingActionButton], floating at the bottom of the screen.
  ///
  /// This is the default alignment of [FloatingActionButton]s in Material applications.
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.trailing] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniEndFloat] and set [FloatingActionButton.mini] to true.
  static const FloatingActionButtonLocation endFloat = _EndFloatFabLocation();

  /// End-aligned [FloatingActionButton], floating at the bottom of the screen,
  /// optimized for mini floating action buttons.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.trailing] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// Compared to [FloatingActionButtonLocation.endFloat], floating action
  /// buttons using this location will move horizontally _and_ vertically
  /// closer to the edges, by [kMiniButtonOffsetAdjustment] each.
  static const FloatingActionButtonLocation miniEndFloat = _MiniEndFloatFabLocation();

  /// Start-aligned [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar.
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.leading] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniStartDocked] and set [FloatingActionButton.mini] to true.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation startDocked = _StartDockedFabLocation();

  /// Start-aligned [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar,
  /// optimized for mini floating action buttons.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.leading] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation miniStartDocked = _MiniStartDockedFabLocation();

  /// Centered [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation centerDocked = _CenterDockedFabLocation();

  /// Centered [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar;
  /// intended to be used with [FloatingActionButton.mini] set to true.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation miniCenterDocked = _MiniCenterDockedFabLocation();

  /// End-aligned [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation endDocked = _EndDockedFabLocation();

  /// End-aligned [FloatingActionButton], floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar,
  /// optimized for mini floating action buttons.
  ///
  /// To align a floating action button with [CircleAvatar]s in the
  /// [ListTile.trailing] slots of [ListTile]s in a [ListView] in the [Scaffold.body],
  /// use [miniEndDocked] and set [FloatingActionButton.mini] to true.
  ///
  /// If the value of [Scaffold.bottomNavigationBar] is a [BottomAppBar],
  /// the bottom app bar can include a "notch" in its shape that accommodates
  /// the overlapping floating action button.
  ///
  /// This is intended to be used with [FloatingActionButton.mini] set to true,
  /// so that the floating action button appears to align with [CircleAvatar]s
  /// in the [ListTile.trailing] slot of a [ListTile] in a [ListView] in the
  /// [Scaffold.body].
  ///
  /// This is unlikely to be a useful location for apps that lack a bottom
  /// navigation bar.
  static const FloatingActionButtonLocation miniEndDocked = _MiniEndDockedFabLocation();

  /// Places the [FloatingActionButton] based on the [Scaffold]'s layout.
  ///
  /// This uses a [ScaffoldPrelayoutGeometry], which the [Scaffold] constructs
  /// during its layout phase after it has laid out every widget it can lay out
  /// except the [FloatingActionButton]. The [Scaffold] uses the [Offset]
  /// returned from this method to position the [FloatingActionButton] and
  /// complete its layout.
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry);

  @override
  String toString() => objectRuntimeType(this, 'FloatingActionButtonLocation');
}

/// A base class that simplifies building [FloatingActionButtonLocation]s when
/// used with mixins [FabTopOffsetY], [FabFloatOffsetY], [FabDockedOffsetY],
/// [FabStartOffsetX], [FabCenterOffsetX], [FabEndOffsetX], and [FabMiniOffsetAdjustment].
///
/// A subclass of [FloatingActionButtonLocation] which implements its [getOffset] method
/// using three other methods: [getOffsetX], [getOffsetY], and [isMini].
///
/// Different mixins on this class override different methods, so that combining
/// a set of mixins creates a floating action button location.
///
/// For example: the location [FloatingActionButtonLocation.miniEndTop]
/// is based on a class that extends [StandardFabLocation]
/// with mixins [FabMiniOffsetAdjustment], [FabEndOffsetX], and [FabTopOffsetY].
///
/// You can create your own subclass of [StandardFabLocation]
/// to implement a custom [FloatingActionButtonLocation].
///
/// {@tool dartpad --template=stateless_widget_material}
///
/// This is an example of a user-defined [FloatingActionButtonLocation].
///
/// The example shows a [Scaffold] with an [AppBar], a [BottomAppBar], and a
/// [FloatingActionButton] using a custom [FloatingActionButtonLocation].
///
/// The new [FloatingActionButtonLocation] is defined
/// by extending [StandardFabLocation] with two mixins,
/// [FabEndOffsetX] and [FabFloatOffsetY], and overriding the
/// [getOffsetX] method to adjust the FAB's x-coordinate, creating a
/// [FloatingActionButtonLocation] slightly different from
/// [FloatingActionButtonLocation.endFloat].
///
/// ```dart preamble
/// class AlmostEndFloatFabLocation extends StandardFabLocation
///     with FabEndOffsetX, FabFloatOffsetY {
///   @override
///   double getOffsetX (ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
///     final double directionalAdjustment =
///       scaffoldGeometry.textDirection == TextDirection.ltr ? -50.0 : 50.0;
///     return super.getOffsetX(scaffoldGeometry, adjustment) + directionalAdjustment;
///   }
/// }
/// ```
///
/// ```dart
/// Widget build(BuildContext context) {
///   return Scaffold(
///     appBar: AppBar(
///       title: Text('Home page'),
///     ),
///     floatingActionButton: FloatingActionButton(
///       onPressed: () { print('FAB pressed.'); },
///       tooltip: 'Increment',
///       child: Icon(Icons.add),
///     ),
///     floatingActionButtonLocation: AlmostEndFloatFabLocation(),
///   );
/// }
/// ```
/// {@end-tool}
///
abstract class StandardFabLocation extends FloatingActionButtonLocation {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const StandardFabLocation();

  /// Obtains the x-offset to place the [FloatingActionButton] based on the
  /// [Scaffold]'s layout.
  ///
  /// Used by [getOffset] to compute its x-coordinate.
  double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment);

  /// Obtains the y-offset to place the [FloatingActionButton] based on the
  /// [Scaffold]'s layout.
  ///
  /// Used by [getOffset] to compute its y-coordinate.
  double getOffsetY(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment);

  /// A function returning whether this [StandardFabLocation] is optimized for
  /// mini [FloatingActionButton]s.
  bool isMini () => false;

  @override
  Offset getOffset(ScaffoldPrelayoutGeometry scaffoldGeometry) {
    final double adjustment = isMini() ? kMiniButtonOffsetAdjustment : 0.0;
    return Offset(
      getOffsetX(scaffoldGeometry, adjustment),
      getOffsetY(scaffoldGeometry, adjustment),
    );
  }

  /// Calculates x-offset for left-aligned [FloatingActionButtonLocation]s.
  static double _leftOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    return kFloatingActionButtonMargin
        + scaffoldGeometry.minInsets.left
        - adjustment;
  }

  /// Calculates x-offset for right-aligned [FloatingActionButtonLocation]s.
  static double _rightOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    return scaffoldGeometry.scaffoldSize.width
        - kFloatingActionButtonMargin
        - scaffoldGeometry.minInsets.right
        - scaffoldGeometry.floatingActionButtonSize.width
        + adjustment;
  }


}

/// Mixin for a "top" floating action button location, such as
/// [FloatingActionButtonLocation.startTop].
///
/// The [adjustment], typically [kMiniButtonOffsetAdjustment], is ignored in the
/// Y axis of "top" positions. For "top" positions, the X offset is adjusted to
/// move closer to the edge of the screen. This is so that a minified floating
/// action button appears to align with [CircleAvatar]s in the
/// [ListTile.leading] slot of a [ListTile] in a [ListView] in the
/// [Scaffold.body].
mixin FabTopOffsetY on StandardFabLocation {
  /// Calculates y-offset for [FloatingActionButtonLocation]s floating over
  /// the transition between the [Scaffold.appBar] and the [Scaffold.body].
  @override
  double getOffsetY(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    if (scaffoldGeometry.contentTop > scaffoldGeometry.minViewPadding.top) {
      final double fabHalfHeight = scaffoldGeometry.floatingActionButtonSize.height / 2.0;
      return scaffoldGeometry.contentTop - fabHalfHeight;
    }
    // Otherwise, ensure we are placed within the bounds of a safe area.
    return scaffoldGeometry.minViewPadding.top;
  }
}

/// Mixin for a "float" floating action button location, such as [FloatingActionButtonLocation.centerFloat].
mixin FabFloatOffsetY on StandardFabLocation {
  /// Calculates y-offset for [FloatingActionButtonLocation]s floating at
  /// the bottom of the screen.
  @override
  double getOffsetY(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    final double contentBottom = scaffoldGeometry.contentBottom;
    final double bottomSheetHeight = scaffoldGeometry.bottomSheetSize.height;
    final double fabHeight = scaffoldGeometry.floatingActionButtonSize.height;
    final double snackBarHeight = scaffoldGeometry.snackBarSize.height;
    final double safeMargin = math.max(
      kFloatingActionButtonMargin,
      scaffoldGeometry.minViewPadding.bottom,
    );

    double fabY = contentBottom - fabHeight - safeMargin;
    if (snackBarHeight > 0.0)
      fabY = math.min(fabY, contentBottom - snackBarHeight - fabHeight - kFloatingActionButtonMargin);
    if (bottomSheetHeight > 0.0)
      fabY = math.min(fabY, contentBottom - bottomSheetHeight - fabHeight / 2.0);

    return fabY + adjustment;
  }
}

/// Mixin for a "docked" floating action button location, such as [FloatingActionButtonLocation.endDocked].
mixin FabDockedOffsetY on StandardFabLocation {
  /// Calculates y-offset for [FloatingActionButtonLocation]s floating over the
  /// [Scaffold.bottomNavigationBar] so that the center of the floating
  /// action button lines up with the top of the bottom navigation bar.
  @override
  double getOffsetY(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    final double contentBottom = scaffoldGeometry.contentBottom;
    final double contentMargin = scaffoldGeometry.scaffoldSize.height - contentBottom;
    final double bottomViewPadding = scaffoldGeometry.minViewPadding.bottom;
    final double bottomSheetHeight = scaffoldGeometry.bottomSheetSize.height;
    final double fabHeight = scaffoldGeometry.floatingActionButtonSize.height;
    final double snackBarHeight = scaffoldGeometry.snackBarSize.height;
    final double safeMargin = bottomViewPadding > contentMargin ? bottomViewPadding : 0.0;

    double fabY = contentBottom - fabHeight / 2.0 - safeMargin;
    // The FAB should sit with a margin between it and the snack bar.
    if (snackBarHeight > 0.0)
      fabY = math.min(fabY, contentBottom - snackBarHeight - fabHeight - kFloatingActionButtonMargin);
    // The FAB should sit with its center in front of the top of the bottom sheet.
    if (bottomSheetHeight > 0.0)
      fabY = math.min(fabY, contentBottom - bottomSheetHeight - fabHeight / 2.0);
    final double maxFabY = scaffoldGeometry.scaffoldSize.height - fabHeight - safeMargin;
    return math.min(maxFabY, fabY);
  }
}

/// Mixin for a "start" floating action button location, such as [FloatingActionButtonLocation.startTop].
mixin FabStartOffsetX on StandardFabLocation {
  /// Calculates x-offset for start-aligned [FloatingActionButtonLocation]s.
  @override
  double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    assert(scaffoldGeometry.textDirection != null);
    switch (scaffoldGeometry.textDirection) {
      case TextDirection.rtl:
        return StandardFabLocation._rightOffsetX(scaffoldGeometry, adjustment);
      case TextDirection.ltr:
        return StandardFabLocation._leftOffsetX(scaffoldGeometry, adjustment);
    }
    return null;
  }
}

/// Mixin for a "center" floating action button location, such as [FloatingActionButtonLocation.centerFloat].
mixin FabCenterOffsetX on StandardFabLocation {
  /// Calculates x-offset for center-aligned [FloatingActionButtonLocation]s.
  @override
  double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    return (scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.floatingActionButtonSize.width) / 2.0;
  }
}

/// Mixin for an "end" floating action button location, such as [FloatingActionButtonLocation.endDocked].
mixin FabEndOffsetX on StandardFabLocation {
  /// Calculates x-offset for end-aligned [FloatingActionButtonLocation]s.
  @override
  double getOffsetX(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
    assert(scaffoldGeometry.textDirection != null);
    switch (scaffoldGeometry.textDirection) {
      case TextDirection.rtl:
        return StandardFabLocation._leftOffsetX(scaffoldGeometry, adjustment);
      case TextDirection.ltr:
        return StandardFabLocation._rightOffsetX(scaffoldGeometry, adjustment);
    }
    return null;
  }
}

/// Mixin for a "mini" floating action button location, such as [FloatingActionButtonLocation.miniStartTop].
mixin FabMiniOffsetAdjustment on StandardFabLocation {
  @override
  bool isMini () => true;
}

class _StartTopFabLocation extends StandardFabLocation
    with FabStartOffsetX, FabTopOffsetY {
  const _StartTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.startTop';
}

class _MiniStartTopFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabStartOffsetX, FabTopOffsetY {
  const _MiniStartTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniStartTop';
}

class _CenterTopFabLocation extends StandardFabLocation
    with FabCenterOffsetX, FabTopOffsetY {
  const _CenterTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.centerTop';
}

class _MiniCenterTopFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabCenterOffsetX, FabTopOffsetY {
  const _MiniCenterTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniCenterTop';
}

class _EndTopFabLocation extends StandardFabLocation
    with FabEndOffsetX, FabTopOffsetY {
  const _EndTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.endTop';
}

class _MiniEndTopFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabEndOffsetX, FabTopOffsetY {
  const _MiniEndTopFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniEndTop';
}

class _StartFloatFabLocation extends StandardFabLocation
    with FabStartOffsetX, FabFloatOffsetY {
  const _StartFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.startFloat';
}

class _MiniStartFloatFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabStartOffsetX, FabFloatOffsetY {
  const _MiniStartFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniStartFloat';
}

class _CenterFloatFabLocation extends StandardFabLocation
    with FabCenterOffsetX, FabFloatOffsetY {
  const _CenterFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.centerFloat';
}

class _MiniCenterFloatFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabCenterOffsetX, FabFloatOffsetY {
  const _MiniCenterFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniCenterFloat';
}

class _EndFloatFabLocation extends StandardFabLocation
    with FabEndOffsetX, FabFloatOffsetY {
  const _EndFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.endFloat';
}

class _MiniEndFloatFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabEndOffsetX, FabFloatOffsetY {
  const _MiniEndFloatFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniEndFloat';
}

class _StartDockedFabLocation extends StandardFabLocation
    with FabStartOffsetX, FabDockedOffsetY {
  const _StartDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.startDocked';
}

class _MiniStartDockedFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabStartOffsetX, FabDockedOffsetY {
  const _MiniStartDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniStartDocked';
}

class _CenterDockedFabLocation extends StandardFabLocation
    with FabCenterOffsetX, FabDockedOffsetY {
  const _CenterDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.centerDocked';
}

class _MiniCenterDockedFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabCenterOffsetX, FabDockedOffsetY {
  const _MiniCenterDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniCenterDocked';
}

class _EndDockedFabLocation extends StandardFabLocation
    with FabEndOffsetX, FabDockedOffsetY {
  const _EndDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.endDocked';
}

class _MiniEndDockedFabLocation extends StandardFabLocation
    with FabMiniOffsetAdjustment, FabEndOffsetX, FabDockedOffsetY {
  const _MiniEndDockedFabLocation();

  @override
  String toString() => 'FloatingActionButtonLocation.miniEndDocked';
}

/// Provider of animations to move the [FloatingActionButton] between [FloatingActionButtonLocation]s.
///
/// The [Scaffold] uses [Scaffold.floatingActionButtonAnimator] to define:
///
///  * The [Offset] of the [FloatingActionButton] between the old and new
///    [FloatingActionButtonLocation]s as part of the transition animation.
///  * An [Animation] to scale the [FloatingActionButton] during the transition.
///  * An [Animation] to rotate the [FloatingActionButton] during the transition.
///  * Where to start a new animation from if an animation is interrupted.
///
/// See also:
///
///  * [FloatingActionButton], which is a circular button typically shown in the
///    bottom right corner of the app.
///  * [FloatingActionButtonLocation], which the [Scaffold] uses to place the
///    [Scaffold.floatingActionButton] within the [Scaffold]'s layout.
abstract class FloatingActionButtonAnimator {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const FloatingActionButtonAnimator();

  /// Moves the [FloatingActionButton] by scaling out and then in at a new
  /// [FloatingActionButtonLocation].
  ///
  /// This animator shrinks the [FloatingActionButton] down until it disappears, then
  /// grows it back to full size at its new [FloatingActionButtonLocation].
  ///
  /// This is the default [FloatingActionButton] motion animation.
  static const FloatingActionButtonAnimator scaling = _ScalingFabMotionAnimator();

  /// Gets the [FloatingActionButton]'s position relative to the origin of the
  /// [Scaffold] based on [progress].
  ///
  /// [begin] is the [Offset] provided by the previous
  /// [FloatingActionButtonLocation].
  ///
  /// [end] is the [Offset] provided by the new
  /// [FloatingActionButtonLocation].
  ///
  /// [progress] is the current progress of the transition animation.
  /// When [progress] is 0.0, the returned [Offset] should be equal to [begin].
  /// when [progress] is 1.0, the returned [Offset] should be equal to [end].
  Offset getOffset({ @required Offset begin, @required Offset end, @required double progress });

  /// Animates the scale of the [FloatingActionButton].
  ///
  /// The animation should both start and end with a value of 1.0.
  ///
  /// For example, to create an animation that linearly scales out and then back in,
  /// you could join animations that pass each other:
  ///
  /// ```dart
  ///   @override
  ///   Animation<double> getScaleAnimation({@required Animation<double> parent}) {
  ///     // The animations will cross at value 0, and the train will return to 1.0.
  ///     return TrainHoppingAnimation(
  ///       Tween<double>(begin: 1.0, end: -1.0).animate(parent),
  ///       Tween<double>(begin: -1.0, end: 1.0).animate(parent),
  ///     );
  ///   }
  /// ```
  Animation<double> getScaleAnimation({ @required Animation<double> parent });

  /// Animates the rotation of [Scaffold.floatingActionButton].
  ///
  /// The animation should both start and end with a value of 0.0 or 1.0.
  ///
  /// The animation values are a fraction of a full circle, with 0.0 and 1.0
  /// corresponding to 0 and 360 degrees, while 0.5 corresponds to 180 degrees.
  ///
  /// For example, to create a rotation animation that rotates the
  /// [FloatingActionButton] through a full circle:
  ///
  /// ```dart
  /// @override
  /// Animation<double> getRotationAnimation({@required Animation<double> parent}) {
  ///   return Tween<double>(begin: 0.0, end: 1.0).animate(parent);
  /// }
  /// ```
  Animation<double> getRotationAnimation({ @required Animation<double> parent });

  /// Gets the progress value to restart a motion animation from when the animation is interrupted.
  ///
  /// [previousValue] is the value of the animation before it was interrupted.
  ///
  /// The restart of the animation will affect all three parts of the motion animation:
  /// offset animation, scale animation, and rotation animation.
  ///
  /// An interruption triggers if the [Scaffold] is given a new [FloatingActionButtonLocation]
  /// while it is still animating a transition between two previous [FloatingActionButtonLocation]s.
  ///
  /// A sensible default is usually 0.0, which is the same as restarting
  /// the animation from the beginning, regardless of the original state of the animation.
  double getAnimationRestart(double previousValue) => 0.0;

  @override
  String toString() => objectRuntimeType(this, 'FloatingActionButtonAnimator');
}

class _ScalingFabMotionAnimator extends FloatingActionButtonAnimator {
  const _ScalingFabMotionAnimator();

  @override
  Offset getOffset({ Offset begin, Offset end, double progress }) {
    if (progress < 0.5) {
      return begin;
    } else {
      return end;
    }
  }

  @override
  Animation<double> getScaleAnimation({ Animation<double> parent }) {
    // Animate the scale down from 1 to 0 in the first half of the animation
    // then from 0 back to 1 in the second half.
    const Curve curve = Interval(0.5, 1.0, curve: Curves.ease);
    return _AnimationSwap<double>(
      ReverseAnimation(parent.drive(CurveTween(curve: curve.flipped))),
      parent.drive(CurveTween(curve: curve)),
      parent,
      0.5,
    );
  }

  // Because we only see the last half of the rotation tween,
  // it needs to go twice as far.
  static final Animatable<double> _rotationTween = Tween<double>(
    begin: 1.0 - kFloatingActionButtonTurnInterval * 2.0,
    end: 1.0,
  );

  static final Animatable<double> _thresholdCenterTween = CurveTween(curve: const Threshold(0.5));

  @override
  Animation<double> getRotationAnimation({ Animation<double> parent }) {
    // This rotation will turn on the way in, but not on the way out.
    return _AnimationSwap<double>(
      parent.drive(_rotationTween),
      ReverseAnimation(parent.drive(_thresholdCenterTween)),
      parent,
      0.5,
    );
  }

  // If the animation was just starting, we'll continue from where we left off.
  // If the animation was finishing, we'll treat it as if we were starting at that point in reverse.
  // This avoids a size jump during the animation.
  @override
  double getAnimationRestart(double previousValue) => math.min(1.0 - previousValue, previousValue);
}

/// An animation that swaps from one animation to the next when the [parent] passes [swapThreshold].
///
/// The [value] of this animation is the value of [first] when [parent.value] < [swapThreshold]
/// and the value of [next] otherwise.
class _AnimationSwap<T> extends CompoundAnimation<T> {
  /// Creates an [_AnimationSwap].
  ///
  /// Both arguments must be non-null. Either can be an [_AnimationSwap] itself
  /// to combine multiple animations.
  _AnimationSwap(Animation<T> first, Animation<T> next, this.parent, this.swapThreshold) : super(first: first, next: next);

  final Animation<double> parent;
  final double swapThreshold;

  @override
  T get value => parent.value < swapThreshold ? first.value : next.value;
}
