// 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/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import 'bottom_app_bar_theme.dart';
import 'elevation_overlay.dart';
import 'material.dart';
import 'scaffold.dart';
import 'theme.dart';

// Examples can assume:
// late Widget bottomAppBarContents;

/// A container that is typically used with [Scaffold.bottomNavigationBar], and
/// can have a notch along the top that makes room for an overlapping
/// [FloatingActionButton].
///
/// Typically used with a [Scaffold] and a [FloatingActionButton].
///
/// {@tool snippet}
/// ```dart
/// Scaffold(
///   bottomNavigationBar: BottomAppBar(
///     color: Colors.white,
///     child: bottomAppBarContents,
///   ),
///   floatingActionButton: const FloatingActionButton(onPressed: null),
/// )
/// ```
/// {@end-tool}
///
/// {@tool dartpad --template=freeform}
/// This example shows the [BottomAppBar], which can be configured to have a notch using the
/// [BottomAppBar.shape] property. This also includes an optional [FloatingActionButton], which illustrates
/// the [FloatingActionButtonLocation]s in relation to the [BottomAppBar].
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart
/// void main() {
///   runApp(const BottomAppBarDemo());
/// }
///
/// class BottomAppBarDemo extends StatefulWidget {
///   const BottomAppBarDemo({Key? key}) : super(key: key);
///
///   @override
///   State createState() => _BottomAppBarDemoState();
/// }
///
/// class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
///   bool _showFab = true;
///   bool _showNotch = true;
///   FloatingActionButtonLocation _fabLocation = FloatingActionButtonLocation.endDocked;
///
///   void _onShowNotchChanged(bool value) {
///     setState(() {
///       _showNotch = value;
///     });
///   }
///
///   void _onShowFabChanged(bool value) {
///     setState(() {
///       _showFab = value;
///     });
///   }
///
///   void _onFabLocationChanged(FloatingActionButtonLocation? value) {
///     setState(() {
///       _fabLocation = value ?? FloatingActionButtonLocation.endDocked;
///     });
///   }
///
///   @override
///   Widget build(BuildContext context) {
///     return MaterialApp(
///       home: Scaffold(
///         appBar: AppBar(
///           automaticallyImplyLeading: false,
///           title: const Text('Bottom App Bar Demo'),
///         ),
///         body: ListView(
///           padding: const EdgeInsets.only(bottom: 88),
///           children: <Widget>[
///             SwitchListTile(
///               title: const Text(
///                 'Floating Action Button',
///               ),
///               value: _showFab,
///               onChanged: _onShowFabChanged,
///             ),
///             SwitchListTile(
///               title: const Text('Notch'),
///               value: _showNotch,
///               onChanged: _onShowNotchChanged,
///             ),
///             const Padding(
///               padding: EdgeInsets.all(16),
///               child: Text('Floating action button position'),
///             ),
///             RadioListTile<FloatingActionButtonLocation>(
///               title: const Text('Docked - End'),
///               value: FloatingActionButtonLocation.endDocked,
///               groupValue: _fabLocation,
///               onChanged: _onFabLocationChanged,
///             ),
///             RadioListTile<FloatingActionButtonLocation>(
///               title: const Text('Docked - Center'),
///               value: FloatingActionButtonLocation.centerDocked,
///               groupValue: _fabLocation,
///               onChanged: _onFabLocationChanged,
///             ),
///             RadioListTile<FloatingActionButtonLocation>(
///               title: const Text('Floating - End'),
///               value: FloatingActionButtonLocation.endFloat,
///               groupValue: _fabLocation,
///               onChanged: _onFabLocationChanged,
///             ),
///             RadioListTile<FloatingActionButtonLocation>(
///               title: const Text('Floating - Center'),
///               value: FloatingActionButtonLocation.centerFloat,
///               groupValue: _fabLocation,
///               onChanged: _onFabLocationChanged,
///             ),
///           ],
///         ),
///         floatingActionButton: _showFab
///             ? FloatingActionButton(
///                 onPressed: () {},
///                 child: const Icon(Icons.add),
///                 tooltip: 'Create',
///               )
///             : null,
///         floatingActionButtonLocation: _fabLocation,
///         bottomNavigationBar: _DemoBottomAppBar(
///           fabLocation: _fabLocation,
///           shape: _showNotch ? const CircularNotchedRectangle() : null,
///         ),
///       ),
///     );
///   }
/// }
///
/// class _DemoBottomAppBar extends StatelessWidget {
///   const _DemoBottomAppBar({
///     this.fabLocation = FloatingActionButtonLocation.endDocked,
///     this.shape = const CircularNotchedRectangle(),
///   });
///
///   final FloatingActionButtonLocation fabLocation;
///   final NotchedShape? shape;
///
///   static final List<FloatingActionButtonLocation> centerLocations = <FloatingActionButtonLocation>[
///     FloatingActionButtonLocation.centerDocked,
///     FloatingActionButtonLocation.centerFloat,
///   ];
///
///   @override
///   Widget build(BuildContext context) {
///     return BottomAppBar(
///       shape: shape,
///       color: Colors.blue,
///       child: IconTheme(
///         data: IconThemeData(color: Theme.of(context).colorScheme.onPrimary),
///         child: Row(
///           children: <Widget>[
///             IconButton(
///               tooltip: 'Open navigation menu',
///               icon: const Icon(Icons.menu),
///               onPressed: () {},
///             ),
///             if (centerLocations.contains(fabLocation)) const Spacer(),
///             IconButton(
///               tooltip: 'Search',
///               icon: const Icon(Icons.search),
///               onPressed: () {},
///             ),
///             IconButton(
///               tooltip: 'Favorite',
///               icon: const Icon(Icons.favorite),
///               onPressed: () {},
///             ),
///           ],
///         ),
///       ),
///     );
///   }
/// }
///
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [NotchedShape] which calculates the notch for a notched [BottomAppBar].
///  * [FloatingActionButton] which the [BottomAppBar] makes a notch for.
///  * [AppBar] for a toolbar that is shown at the top of the screen.
class BottomAppBar extends StatefulWidget {
  /// Creates a bottom application bar.
  ///
  /// The [clipBehavior] argument defaults to [Clip.none] and must not be null.
  /// Additionally, [elevation] must be non-negative.
  ///
  /// If [color], [elevation], or [shape] are null, their [BottomAppBarTheme] values will be used.
  /// If the corresponding [BottomAppBarTheme] property is null, then the default
  /// specified in the property's documentation will be used.
  const BottomAppBar({
    Key? key,
    this.color,
    this.elevation,
    this.shape,
    this.clipBehavior = Clip.none,
    this.notchMargin = 4.0,
    this.child,
  }) : assert(elevation == null || elevation >= 0.0),
       assert(notchMargin != null),
       assert(clipBehavior != null),
       super(key: key);

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  ///
  /// Typically this the child will be a [Row], with the first child
  /// being an [IconButton] with the [Icons.menu] icon.
  final Widget? child;

  /// The bottom app bar's background color.
  ///
  /// If this property is null then [BottomAppBarTheme.color] of
  /// [ThemeData.bottomAppBarTheme] is used. If that's null then
  /// [ThemeData.bottomAppBarColor] is used.
  final Color? color;

  /// The z-coordinate at which to place this bottom app bar relative to its
  /// parent.
  ///
  /// This controls the size of the shadow below the bottom app bar. The
  /// value is non-negative.
  ///
  /// If this property is null then [BottomAppBarTheme.elevation] of
  /// [ThemeData.bottomAppBarTheme] is used. If that's null, the default value
  /// is 8.
  final double? elevation;

  /// The notch that is made for the floating action button.
  ///
  /// If this property is null then [BottomAppBarTheme.shape] of
  /// [ThemeData.bottomAppBarTheme] is used. If that's null then the shape will
  /// be rectangular with no notch.
  final NotchedShape? shape;

  /// {@macro flutter.material.Material.clipBehavior}
  ///
  /// Defaults to [Clip.none], and must not be null.
  final Clip clipBehavior;

  /// The margin between the [FloatingActionButton] and the [BottomAppBar]'s
  /// notch.
  ///
  /// Not used if [shape] is null.
  final double notchMargin;

  @override
  State createState() => _BottomAppBarState();
}

class _BottomAppBarState extends State<BottomAppBar> {
  late ValueListenable<ScaffoldGeometry> geometryListenable;
  final GlobalKey materialKey = GlobalKey();
  static const double _defaultElevation = 8.0;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    geometryListenable = Scaffold.geometryOf(context);
  }

  @override
  Widget build(BuildContext context) {
    final BottomAppBarTheme babTheme = BottomAppBarTheme.of(context);
    final NotchedShape? notchedShape = widget.shape ?? babTheme.shape;
    final CustomClipper<Path> clipper = notchedShape != null
      ? _BottomAppBarClipper(
          geometry: geometryListenable,
          shape: notchedShape,
          materialKey: materialKey,
          notchMargin: widget.notchMargin,
        )
      : const ShapeBorderClipper(shape: RoundedRectangleBorder());
    final double elevation = widget.elevation ?? babTheme.elevation ?? _defaultElevation;
    final Color color = widget.color ?? babTheme.color ?? Theme.of(context).bottomAppBarColor;
    final Color effectiveColor = ElevationOverlay.applyOverlay(context, color, elevation);
    return PhysicalShape(
      clipper: clipper,
      elevation: elevation,
      color: effectiveColor,
      clipBehavior: widget.clipBehavior,
      child: Material(
        key: materialKey,
        type: MaterialType.transparency,
        child: widget.child == null
          ? null
          : SafeArea(child: widget.child!),
      ),
    );
  }
}

class _BottomAppBarClipper extends CustomClipper<Path> {
  const _BottomAppBarClipper({
    required this.geometry,
    required this.shape,
    required this.materialKey,
    required this.notchMargin,
  }) : assert(geometry != null),
       assert(shape != null),
       assert(notchMargin != null),
       super(reclip: geometry);

  final ValueListenable<ScaffoldGeometry> geometry;
  final NotchedShape shape;
  final GlobalKey materialKey;
  final double notchMargin;

  // Returns the top of the BottomAppBar in global coordinates.
  double get bottomNavigationBarTop {
    final RenderBox? box = materialKey.currentContext?.findRenderObject() as RenderBox?;
    return box?.localToGlobal(Offset.zero).dy ?? 0;
  }

  @override
  Path getClip(Size size) {
    // button is the floating action button's bounding rectangle in the
    // coordinate system whose origin is at the appBar's top left corner,
    // or null if there is no floating action button.
    final Rect? button = geometry.value.floatingActionButtonArea?.translate(0.0, bottomNavigationBarTop * -1.0);
    return shape.getOuterPath(Offset.zero & size, button?.inflate(notchMargin));
  }

  @override
  bool shouldReclip(_BottomAppBarClipper oldClipper) {
    return oldClipper.geometry != geometry
        || oldClipper.shape != shape
        || oldClipper.notchMargin != notchMargin;
  }
}
