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

/// @docImport 'nav_bar.dart';
library;

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

import 'colors.dart';
import 'constants.dart';
import 'text_theme.dart';
import 'theme.dart';

// Measured against iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).

/// The size of a [CupertinoButton].
/// Based on the iOS (17) [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
enum CupertinoButtonSize {
  /// Displays a smaller button with round sides and smaller text (uses [CupertinoTextThemeData.actionSmallTextStyle]).
  small,

  /// Displays a medium sized button with round sides and regular-sized text.
  medium,

  /// Displays a (classic) large button with rounded edges and regular-sized text.
  large,
}

/// The style of a [CupertinoButton] that changes the style of the button's background.
///
/// Based on the iOS Human Interface Guidelines (https://developer.apple.com/design/human-interface-guidelines/buttons#iOS-iPadOS).
enum _CupertinoButtonStyle {
  /// No background or border, primary foreground color.
  plain,

  /// Translucent background, primary foreground color.
  tinted,

  /// Solid background, contrasting foreground color.
  filled,
}

/// An iOS-style button.
///
/// Takes in a text or an icon that fades out and in on touch. May optionally have a
/// background.
///
/// The [padding] defaults to 16.0 pixels. When using a [CupertinoButton] within
/// a fixed height parent, like a [CupertinoNavigationBar], a smaller, or even
/// [EdgeInsets.zero], should be used to prevent clipping larger [child]
/// widgets.
///
/// Preserves any parent [IconThemeData] but overwrites its [IconThemeData.color]
/// with the [CupertinoThemeData.primaryColor] (or
/// [CupertinoThemeData.primaryContrastingColor] if the button is disabled).
///
/// {@tool dartpad}
/// This sample shows produces an enabled and disabled [CupertinoButton] and
/// [CupertinoButton.filled].
///
/// ** See code in examples/api/lib/cupertino/button/cupertino_button.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * <https://developer.apple.com/design/human-interface-guidelines/buttons/>
class CupertinoButton extends StatefulWidget {
  /// Creates an iOS-style button.
  const CupertinoButton({
    super.key,
    required this.child,
    this.sizeStyle = CupertinoButtonSize.large,
    this.padding,
    this.color,
    this.foregroundColor,
    this.disabledColor = CupertinoColors.quaternarySystemFill,
    @Deprecated(
      'Use minimumSize instead. '
      'This feature was deprecated after v3.28.0-3.0.pre.',
    )
    this.minSize,
    this.minimumSize,
    this.pressedOpacity = 0.4,
    this.borderRadius,
    this.alignment = Alignment.center,
    this.focusColor,
    this.focusNode,
    this.onFocusChange,
    this.autofocus = false,
    this.mouseCursor,
    this.onLongPress,
    required this.onPressed,
  }) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
       assert(minimumSize == null || minSize == null),
       _style = _CupertinoButtonStyle.plain;

  /// Creates an iOS-style button with a tinted background.
  ///
  /// The background color is derived from the [CupertinoTheme]'s `primaryColor` + transparency.
  /// The foreground color is the [CupertinoTheme]'s `primaryColor`.
  ///
  /// To specify a custom background color, use the [color] argument of the
  /// default constructor.
  ///
  /// To match the iOS "grey" button style, set [color] to [CupertinoColors.systemGrey].
  const CupertinoButton.tinted({
    super.key,
    required this.child,
    this.sizeStyle = CupertinoButtonSize.large,
    this.padding,
    this.color,
    this.foregroundColor,
    this.disabledColor = CupertinoColors.tertiarySystemFill,
    @Deprecated(
      'Use minimumSize instead. '
      'This feature was deprecated after v3.28.0-3.0.pre.',
    )
    this.minSize,
    this.minimumSize,
    this.pressedOpacity = 0.4,
    this.borderRadius,
    this.alignment = Alignment.center,
    this.focusColor,
    this.focusNode,
    this.onFocusChange,
    this.autofocus = false,
    this.mouseCursor,
    this.onLongPress,
    required this.onPressed,
  }) : assert(minimumSize == null || minSize == null),
       _style = _CupertinoButtonStyle.tinted;

  /// Creates an iOS-style button with a filled background.
  ///
  /// The background color is derived from the [color] argument.
  /// The foreground color is the [CupertinoTheme]'s `primaryContrastingColor`.
  const CupertinoButton.filled({
    super.key,
    required this.child,
    this.sizeStyle = CupertinoButtonSize.large,
    this.padding,
    this.color,
    this.disabledColor = CupertinoColors.tertiarySystemFill,
    this.foregroundColor,
    @Deprecated(
      'Use minimumSize instead. '
      'This feature was deprecated after v3.28.0-3.0.pre.',
    )
    this.minSize,
    this.minimumSize,
    this.pressedOpacity = 0.4,
    this.borderRadius,
    this.alignment = Alignment.center,
    this.focusColor,
    this.focusNode,
    this.onFocusChange,
    this.autofocus = false,
    this.mouseCursor,
    this.onLongPress,
    required this.onPressed,
  }) : assert(pressedOpacity == null || (pressedOpacity >= 0.0 && pressedOpacity <= 1.0)),
       assert(minimumSize == null || minSize == null),
       _style = _CupertinoButtonStyle.filled;

  /// The widget below this widget in the tree.
  ///
  /// Typically a [Text] widget.
  final Widget child;

  /// The amount of space to surround the child inside the bounds of the button.
  ///
  /// Defaults to 16.0 pixels.
  final EdgeInsetsGeometry? padding;

  /// The color of the button's background.
  ///
  /// Defaults to null which produces a button with no background or border.
  ///
  /// Defaults to the [CupertinoTheme]'s `primaryColor` when the
  /// [CupertinoButton.filled] constructor is used.
  final Color? color;

  /// The color of the button's background when the button is disabled.
  ///
  /// Ignored if the [CupertinoButton] doesn't also have a [color].
  ///
  /// Defaults to [CupertinoColors.quaternarySystemFill] when [color] is
  /// specified.
  final Color disabledColor;

  /// The color of the button's text and icons.
  ///
  /// Defaults to the [CupertinoTheme]'s `primaryColor` when the
  /// [CupertinoButton.filled] constructor is used.
  final Color? foregroundColor;

  /// The callback that is called when the button is tapped or otherwise activated.
  ///
  /// If [onPressed] and [onLongPress] callbacks are null, then the button will be disabled.
  final VoidCallback? onPressed;

  /// If [onPressed] and [onLongPress] callbacks are null, then the button will be disabled.
  final VoidCallback? onLongPress;

  /// Minimum size of the button.
  ///
  /// Defaults to kMinInteractiveDimensionCupertino which the iOS Human
  /// Interface Guidelines recommends as the minimum tappable area.
  @Deprecated(
    'Use minimumSize instead. '
    'This feature was deprecated after v3.28.0-3.0.pre.',
  )
  final double? minSize;

  /// The minimum size of the button.
  ///
  /// Defaults to a button with a height and a width of
  /// [kMinInteractiveDimensionCupertino], which the iOS Human
  /// Interface Guidelines recommends as the minimum tappable area.
  final Size? minimumSize;

  /// The opacity that the button will fade to when it is pressed.
  /// The button will have an opacity of 1.0 when it is not pressed.
  ///
  /// This defaults to 0.4. If null, opacity will not change on pressed if using
  /// your own custom effects is desired.
  final double? pressedOpacity;

  /// The radius of the button's corners when it has a background color.
  ///
  /// Defaults to [kCupertinoButtonSizeBorderRadius], based on [sizeStyle].
  final BorderRadius? borderRadius;

  /// The size of the button.
  ///
  /// Defaults to [CupertinoButtonSize.large].
  final CupertinoButtonSize sizeStyle;

  /// The alignment of the button's [child].
  ///
  /// Typically buttons are sized to be just big enough to contain the child and its
  /// [padding]. If the button's size is constrained to a fixed size, for example by
  /// enclosing it with a [SizedBox], this property defines how the child is aligned
  /// within the available space.
  ///
  /// Always defaults to [Alignment.center].
  final AlignmentGeometry alignment;

  /// The color to use for the focus highlight for keyboard interactions.
  ///
  /// Defaults to a slightly transparent [color]. If [color] is null, defaults
  /// to a slightly transparent [CupertinoColors.activeBlue]. Slightly
  /// transparent in this context means the color is used with an opacity of
  /// 0.80, a brightness of 0.69 and a saturation of 0.835.
  final Color? focusColor;

  /// {@macro flutter.widgets.Focus.focusNode}
  final FocusNode? focusNode;

  /// Handler called when the focus changes.
  ///
  /// Called with true if this widget's node gains focus, and false if it loses
  /// focus.
  final ValueChanged<bool>? onFocusChange;

  /// {@macro flutter.widgets.Focus.autofocus}
  final bool autofocus;

  /// The cursor for a mouse pointer when it enters or is hovering over the widget.
  ///
  /// If [mouseCursor] is a [WidgetStateMouseCursor],
  /// [WidgetStateProperty.resolve] is used for the following [WidgetState]:
  ///  * [WidgetState.disabled].
  ///  * [WidgetState.pressed].
  ///  * [WidgetState.focused].
  ///
  /// If null, then [MouseCursor.defer] is used when the button is disabled.
  /// When the button is enabled, [SystemMouseCursors.click] is used on Web
  /// and [MouseCursor.defer] is used on other platforms.
  ///
  /// See also:
  ///
  ///  * [WidgetStateMouseCursor], a [MouseCursor] that implements
  ///    [WidgetStateProperty] which is used in APIs that need to accept
  ///    either a [MouseCursor] or a [WidgetStateProperty].
  final MouseCursor? mouseCursor;

  final _CupertinoButtonStyle _style;

  /// Whether the button is enabled or disabled. Buttons are disabled by default. To
  /// enable a button, set [onPressed] or [onLongPress] to a non-null value.
  bool get enabled => onPressed != null || onLongPress != null;

  /// The distance a button needs to be moved after being pressed for its opacity to change.
  ///
  /// The opacity changes when the position moved is this distance away from the button.
  static double tapMoveSlop() {
    return switch (defaultTargetPlatform) {
      TargetPlatform.iOS ||
      TargetPlatform.android ||
      TargetPlatform.fuchsia => kCupertinoButtonTapMoveSlop,
      TargetPlatform.macOS || TargetPlatform.linux || TargetPlatform.windows => 0.0,
    };
  }

  @override
  State<CupertinoButton> createState() => _CupertinoButtonState();

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(FlagProperty('enabled', value: enabled, ifFalse: 'disabled'));
  }
}

class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProviderStateMixin {
  // Eyeballed values. Feel free to tweak.
  static const Duration kFadeOutDuration = Duration(milliseconds: 120);
  static const Duration kFadeInDuration = Duration(milliseconds: 180);
  final Tween<double> _opacityTween = Tween<double>(begin: 1.0);

  late AnimationController _animationController;
  late Animation<double> _opacityAnimation;

  late bool isFocused;

  static final WidgetStateProperty<MouseCursor> _defaultCursor =
      WidgetStateProperty.resolveWith<MouseCursor>((Set<WidgetState> states) {
        return !states.contains(WidgetState.disabled) && kIsWeb
            ? SystemMouseCursors.click
            : MouseCursor.defer;
      });

  @override
  void initState() {
    super.initState();
    isFocused = false;
    _animationController = AnimationController(
      duration: const Duration(milliseconds: 200),
      value: 0.0,
      vsync: this,
    );
    _opacityAnimation = _animationController
        .drive(CurveTween(curve: Curves.decelerate))
        .drive(_opacityTween);
    _setTween();
  }

  @override
  void didUpdateWidget(CupertinoButton old) {
    super.didUpdateWidget(old);
    _setTween();
  }

  void _setTween() {
    _opacityTween.end = widget.pressedOpacity ?? 1.0;
  }

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

  bool _buttonHeldDown = false;
  bool _tapInProgress = false;

  void _handleTapDown(TapDownDetails event) {
    setState(() {
      _tapInProgress = true;
    });
    if (!_buttonHeldDown) {
      _buttonHeldDown = true;
      _animate();
    }
  }

  void _handleTapUp(TapUpDetails event) {
    setState(() {
      _tapInProgress = false;
    });
    if (_buttonHeldDown) {
      _buttonHeldDown = false;
      _animate();
    }
    final renderObject = context.findRenderObject()! as RenderBox;
    final Offset localPosition = renderObject.globalToLocal(event.globalPosition);
    if (renderObject.paintBounds.inflate(CupertinoButton.tapMoveSlop()).contains(localPosition)) {
      _handleTap();
    }
  }

  void _handleTapCancel() {
    setState(() {
      _tapInProgress = false;
    });
    if (_buttonHeldDown) {
      _buttonHeldDown = false;
      _animate();
    }
  }

  void _handleTapMove(TapMoveDetails event) {
    final renderObject = context.findRenderObject()! as RenderBox;
    final Offset localPosition = renderObject.globalToLocal(event.globalPosition);
    final bool buttonShouldHeldDown = renderObject.paintBounds
        .inflate(CupertinoButton.tapMoveSlop())
        .contains(localPosition);
    if (_tapInProgress && buttonShouldHeldDown != _buttonHeldDown) {
      _buttonHeldDown = buttonShouldHeldDown;
      _animate();
    }
  }

  void _handleTap([Intent? _]) {
    if (widget.onPressed != null) {
      widget.onPressed!();
      context.findRenderObject()!.sendSemanticsEvent(const TapSemanticEvent());
    }
  }

  void _animate() {
    if (_animationController.isAnimating) {
      return;
    }
    final bool wasHeldDown = _buttonHeldDown;
    final TickerFuture ticker = _buttonHeldDown
        ? _animationController.animateTo(
            1.0,
            duration: kFadeOutDuration,
            curve: Curves.easeInOutCubicEmphasized,
          )
        : _animationController.animateTo(
            0.0,
            duration: kFadeInDuration,
            curve: Curves.easeOutCubic,
          );
    ticker.then<void>((void value) {
      if (mounted && wasHeldDown != _buttonHeldDown) {
        _animate();
      }
    });
  }

  void _onShowFocusHighlight(bool showHighlight) {
    setState(() {
      isFocused = showHighlight;
    });
  }

  late final Map<Type, Action<Intent>> _actionMap = <Type, Action<Intent>>{
    ActivateIntent: CallbackAction<ActivateIntent>(onInvoke: _handleTap),
  };

  @override
  Widget build(BuildContext context) {
    final bool enabled = widget.enabled;
    final Size? minimumSize = widget.minimumSize == null
        ? widget.minSize == null
              ? null
              : Size(widget.minSize!, widget.minSize!)
        : widget.minimumSize!;
    final CupertinoThemeData themeData = CupertinoTheme.of(context);
    final Color primaryColor = themeData.primaryColor;
    final Color? backgroundColor =
        (widget.color == null
                ? widget._style != _CupertinoButtonStyle.plain
                      ? primaryColor
                      : null
                : CupertinoDynamicColor.maybeResolve(widget.color, context))
            ?.withOpacity(
              widget._style == _CupertinoButtonStyle.tinted
                  ? CupertinoTheme.brightnessOf(context) == Brightness.light
                        ? kCupertinoButtonTintedOpacityLight
                        : kCupertinoButtonTintedOpacityDark
                  : widget.color?.opacity ?? 1.0,
            );
    final Color effectiveForegroundColor =
        widget.foregroundColor ??
        switch ((widget._style, enabled)) {
          (_CupertinoButtonStyle.filled, _) => themeData.primaryContrastingColor,
          (_, true) => primaryColor,
          (_, false) => CupertinoDynamicColor.resolve(CupertinoColors.tertiaryLabel, context),
        };

    final Color effectiveFocusOutlineColor =
        widget.focusColor ??
        HSLColor.fromColor(
              (backgroundColor ?? CupertinoColors.activeBlue).withOpacity(
                kCupertinoFocusColorOpacity,
              ),
            )
            .withLightness(kCupertinoFocusColorBrightness)
            .withSaturation(kCupertinoFocusColorSaturation)
            .toColor();

    final TextStyle textStyle =
        (widget.sizeStyle == CupertinoButtonSize.small
                ? themeData.textTheme.actionSmallTextStyle
                : themeData.textTheme.actionTextStyle)
            .copyWith(color: effectiveForegroundColor);
    final IconThemeData iconTheme = IconTheme.of(context).copyWith(
      color: effectiveForegroundColor,
      size: textStyle.fontSize != null
          ? textStyle.fontSize! * 1.2
          : kCupertinoButtonDefaultIconSize,
    );

    final DeviceGestureSettings? gestureSettings = MediaQuery.maybeGestureSettingsOf(context);

    final states = <WidgetState>{
      if (!enabled) WidgetState.disabled,
      if (_tapInProgress) WidgetState.pressed,
      if (isFocused) WidgetState.focused,
    };
    final MouseCursor effectiveMouseCursor =
        WidgetStateProperty.resolveAs<MouseCursor?>(widget.mouseCursor, states) ??
        _defaultCursor.resolve(states);

    final shapeDecoration = ShapeDecoration(
      shape: RoundedSuperellipseBorder(
        side: enabled && isFocused
            ? BorderSide(
                color: effectiveFocusOutlineColor,
                width: 3.5,
                strokeAlign: BorderSide.strokeAlignOutside,
              )
            : BorderSide.none,
        borderRadius: widget.borderRadius ?? kCupertinoButtonSizeBorderRadius[widget.sizeStyle],
      ),
      color: backgroundColor != null && !enabled
          ? CupertinoDynamicColor.resolve(widget.disabledColor, context)
          : backgroundColor,
    );

    return MouseRegion(
      cursor: effectiveMouseCursor,
      child: FocusableActionDetector(
        actions: _actionMap,
        focusNode: widget.focusNode,
        autofocus: widget.autofocus,
        onFocusChange: widget.onFocusChange,
        onShowFocusHighlight: _onShowFocusHighlight,
        enabled: enabled,
        child: RawGestureDetector(
          behavior: HitTestBehavior.opaque,
          gestures: <Type, GestureRecognizerFactory>{
            TapGestureRecognizer: GestureRecognizerFactoryWithHandlers<TapGestureRecognizer>(
              () => TapGestureRecognizer(postAcceptSlopTolerance: null),
              (TapGestureRecognizer instance) {
                instance.onTapDown = enabled ? _handleTapDown : null;
                instance.onTapUp = enabled ? _handleTapUp : null;
                instance.onTapCancel = enabled ? _handleTapCancel : null;
                instance.onTapMove = enabled ? _handleTapMove : null;
                instance.gestureSettings = gestureSettings;
              },
            ),
            if (widget.onLongPress != null)
              LongPressGestureRecognizer:
                  GestureRecognizerFactoryWithHandlers<LongPressGestureRecognizer>(
                    () => LongPressGestureRecognizer(),
                    (LongPressGestureRecognizer instance) {
                      instance.onLongPress = widget.onLongPress;
                      instance.gestureSettings = gestureSettings;
                    },
                  ),
          },
          child: Semantics(
            button: true,
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minWidth:
                    minimumSize?.width ??
                    kCupertinoButtonMinSize[widget.sizeStyle] ??
                    kMinInteractiveDimensionCupertino,
                minHeight:
                    minimumSize?.height ??
                    kCupertinoButtonMinSize[widget.sizeStyle] ??
                    kMinInteractiveDimensionCupertino,
              ),
              child: FadeTransition(
                opacity: _opacityAnimation,
                child: DecoratedBox(
                  decoration: shapeDecoration,
                  child: Padding(
                    padding: widget.padding ?? kCupertinoButtonPadding[widget.sizeStyle]!,
                    child: Align(
                      alignment: widget.alignment,
                      widthFactor: 1.0,
                      heightFactor: 1.0,
                      child: DefaultTextStyle(
                        style: textStyle,
                        child: IconTheme(data: iconTheme, child: widget.child),
                      ),
                    ),
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}
