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

import 'button_style.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'debug.dart';
import 'icons.dart';
import 'ink_well.dart';
import 'material.dart';
import 'material_localizations.dart';
import 'material_state.dart';
import 'text_button.dart';
import 'text_theme.dart';
import 'theme.dart';

// TODO(dragostis): Missing functionality:
//   * mobile horizontal mode with adding/removing steps
//   * alternative labeling
//   * stepper feedback in the case of high-latency interactions

/// The state of a [Step] which is used to control the style of the circle and
/// text.
///
/// See also:
///
///  * [Step]
enum StepState {
  /// A step that displays its index in its circle.
  indexed,

  /// A step that displays a pencil icon in its circle.
  editing,

  /// A step that displays a tick icon in its circle.
  complete,

  /// A step that is disabled and does not to react to taps.
  disabled,

  /// A step that is currently having an error. e.g. the user has submitted wrong
  /// input.
  error,
}

/// Defines the [Stepper]'s main axis.
enum StepperType {
  /// A vertical layout of the steps with their content in-between the titles.
  vertical,

  /// A horizontal layout of the steps with their content below the titles.
  horizontal,
}

/// Container for all the information necessary to build a Stepper widget's
/// forward and backward controls for any given step.
///
/// Used by [Stepper.controlsBuilder].
@immutable
class ControlsDetails {
  /// Creates a set of details describing the Stepper.
  const ControlsDetails({
    required this.currentStep,
    required this.stepIndex,
    this.onStepCancel,
    this.onStepContinue,
  });

  /// Index that is active for the surrounding [Stepper] widget. This may be
  /// different from [stepIndex] if the user has just changed steps and we are
  /// currently animating toward that step.
  final int currentStep;

  /// Index of the step for which these controls are being built. This is
  /// not necessarily the active index, if the user has just changed steps and
  /// this step is animating away. To determine whether a given builder is building
  /// the active step or the step being navigated away from, see [isActive].
  final int stepIndex;

  /// The callback called when the 'continue' button is tapped.
  ///
  /// If null, the 'continue' button will be disabled.
  final VoidCallback? onStepContinue;

  /// The callback called when the 'cancel' button is tapped.
  ///
  /// If null, the 'cancel' button will be disabled.
  final VoidCallback? onStepCancel;

  /// True if the indicated step is also the current active step. If the user has
  /// just activated the transition to a new step, some [Stepper.type] values will
  /// lead to both steps being rendered for the duration of the animation shifting
  /// between steps.
  bool get isActive => currentStep == stepIndex;
}

/// A builder that creates a widget given the two callbacks `onStepContinue` and
/// `onStepCancel`.
///
/// Used by [Stepper.controlsBuilder].
///
/// See also:
///
///  * [WidgetBuilder], which is similar but only takes a [BuildContext].
typedef ControlsWidgetBuilder = Widget Function(BuildContext context, ControlsDetails details);

/// A builder that creates the icon widget for the [Step] at [stepIndex], given
/// [stepState].
typedef StepIconBuilder = Widget? Function(int stepIndex, StepState stepState);

const TextStyle _kStepStyle = TextStyle(fontSize: 12.0, color: Colors.white);
const Color _kErrorLight = Colors.red;
final Color _kErrorDark = Colors.red.shade400;
const Color _kCircleActiveLight = Colors.white;
const Color _kCircleActiveDark = Colors.black87;
const Color _kDisabledLight = Colors.black38;
const Color _kDisabledDark = Colors.white38;
const double _kStepSize = 24.0;
const double _kTriangleSqrt = 0.866025; // sqrt(3.0) / 2.0
const double _kTriangleHeight = _kStepSize * _kTriangleSqrt;
const double _kMaxStepSize = 80.0;
const EdgeInsetsDirectional _kDefaultVerticalContentPadding = EdgeInsetsDirectional.only(
  start: 60.0,
  end: 24.0,
  bottom: 24.0,
);
const EdgeInsets _kDefaultHorizontalContentPadding = EdgeInsets.all(24.0);
const EdgeInsetsGeometry _kDefaultHeaderPadding = EdgeInsets.symmetric(horizontal: 24.0);

/// A material step used in [Stepper]. The step can have a title and subtitle,
/// an icon within its circle, some content and a state that governs its
/// styling.
///
/// See also:
///
///  * [Stepper]
///  * <https://material.io/archive/guidelines/components/steppers.html>
@immutable
class Step {
  /// Creates a step for a [Stepper].
  const Step({
    required this.title,
    this.subtitle,
    required this.content,
    this.state = StepState.indexed,
    this.isActive = false,
    this.label,
    this.stepStyle,
  });

  /// The title of the step that typically describes it.
  final Widget title;

  /// The subtitle of the step that appears below the title and has a smaller
  /// font size. It typically gives more details that complement the title.
  ///
  /// If null, the subtitle is not shown.
  final Widget? subtitle;

  /// The content of the step that appears below the [title] and [subtitle].
  ///
  /// Below the content, every step has a 'continue' and 'cancel' button.
  final Widget content;

  /// The state of the step which determines the styling of its components
  /// and whether steps are interactive.
  final StepState state;

  /// Whether or not the step is active. The flag only influences styling.
  final bool isActive;

  /// Only [StepperType.horizontal], Optional widget that appears under the [title].
  /// By default, uses the `bodyLarge` theme.
  final Widget? label;

  /// Optional overrides for the step's default visual configuration.
  final StepStyle? stepStyle;
}

/// A material stepper widget that displays progress through a sequence of
/// steps. Steppers are particularly useful in the case of forms where one step
/// requires the completion of another one, or where multiple steps need to be
/// completed in order to submit the whole form.
///
/// The widget is a flexible wrapper. A parent class should pass [currentStep]
/// to this widget based on some logic triggered by the three callbacks that it
/// provides.
///
/// {@tool dartpad}
/// An example the shows how to use the [Stepper], and the [Stepper] UI
/// appearance.
///
/// ** See code in examples/api/lib/material/stepper/stepper.0.dart **
/// {@end-tool}
///
/// See also:
///
///  * [Step]
///  * <https://material.io/archive/guidelines/components/steppers.html>
class Stepper extends StatefulWidget {
  /// Creates a stepper from a list of steps.
  ///
  /// This widget is not meant to be rebuilt with a different list of steps
  /// unless a key is provided in order to distinguish the old stepper from the
  /// new one.
  const Stepper({
    super.key,
    required this.steps,
    this.controller,
    this.physics,
    this.type = StepperType.vertical,
    this.currentStep = 0,
    this.onStepTapped,
    this.onStepContinue,
    this.onStepCancel,
    this.controlsBuilder,
    this.elevation,
    this.margin,
    this.connectorColor,
    this.connectorThickness,
    this.stepIconBuilder,
    this.stepIconHeight,
    this.stepIconWidth,
    this.stepIconMargin,
    this.clipBehavior = Clip.none,
    this.headerPadding,
    this.contentPadding,
  }) : assert(0 <= currentStep && currentStep < steps.length),
       assert(
         stepIconHeight == null ||
             (stepIconHeight >= _kStepSize && stepIconHeight <= _kMaxStepSize),
         'stepIconHeight must be greater than $_kStepSize and less or equal to $_kMaxStepSize',
       ),
       assert(
         stepIconWidth == null || (stepIconWidth >= _kStepSize && stepIconWidth <= _kMaxStepSize),
         'stepIconWidth must be greater than $_kStepSize and less or equal to $_kMaxStepSize',
       ),
       assert(
         stepIconHeight == null || stepIconWidth == null || stepIconHeight == stepIconWidth,
         'If either stepIconHeight or stepIconWidth is specified, both must be specified and '
         'the values must be equal.',
       );

  /// The steps of the stepper whose titles, subtitles, icons always get shown.
  ///
  /// The length of [steps] must not change.
  final List<Step> steps;

  /// How the stepper's scroll view should respond to user input.
  ///
  /// For example, determines how the scroll view continues to
  /// animate after the user stops dragging the scroll view.
  ///
  /// If the stepper is contained within another scrollable it
  /// can be helpful to set this property to [ClampingScrollPhysics].
  final ScrollPhysics? physics;

  /// An object that can be used to control the position to which this scroll
  /// view is scrolled.
  ///
  /// To control the initial scroll offset of the scroll view, provide a
  /// [controller] with its [ScrollController.initialScrollOffset] property set.
  final ScrollController? controller;

  /// The type of stepper that determines the layout. In the case of
  /// [StepperType.horizontal], the content of the current step is displayed
  /// underneath as opposed to the [StepperType.vertical] case where it is
  /// displayed in-between.
  final StepperType type;

  /// The index into [steps] of the current step whose content is displayed.
  final int currentStep;

  /// The callback called when a step is tapped, with its index passed as
  /// an argument.
  final ValueChanged<int>? onStepTapped;

  /// The callback called when the 'continue' button is tapped.
  ///
  /// If null, the 'continue' button will be disabled.
  final VoidCallback? onStepContinue;

  /// The callback called when the 'cancel' button is tapped.
  ///
  /// If null, the 'cancel' button will be disabled.
  final VoidCallback? onStepCancel;

  /// The callback for creating custom controls.
  ///
  /// If null, the default controls from the current theme will be used.
  ///
  /// This callback which takes in a context and a [ControlsDetails] object, which
  /// contains step information and two functions: [onStepContinue] and [onStepCancel].
  /// These can be used to control the stepper. For example, reading the
  /// [ControlsDetails.currentStep] value within the callback can change the text
  /// of the continue or cancel button depending on which step users are at.
  ///
  /// {@tool dartpad}
  /// Creates a stepper control with custom buttons.
  ///
  /// ```dart
  /// Widget build(BuildContext context) {
  ///   return Stepper(
  ///     controlsBuilder:
  ///       (BuildContext context, ControlsDetails details) {
  ///          return Row(
  ///            children: <Widget>[
  ///              TextButton(
  ///                onPressed: details.onStepContinue,
  ///                child: Text('Continue to Step ${details.stepIndex + 1}'),
  ///              ),
  ///              TextButton(
  ///                onPressed: details.onStepCancel,
  ///                child: Text('Back to Step ${details.stepIndex - 1}'),
  ///              ),
  ///            ],
  ///          );
  ///       },
  ///     steps: const <Step>[
  ///       Step(
  ///         title: Text('A'),
  ///         content: SizedBox(
  ///           width: 100.0,
  ///           height: 100.0,
  ///         ),
  ///       ),
  ///       Step(
  ///         title: Text('B'),
  ///         content: SizedBox(
  ///           width: 100.0,
  ///           height: 100.0,
  ///         ),
  ///       ),
  ///     ],
  ///   );
  /// }
  /// ```
  /// ** See code in examples/api/lib/material/stepper/stepper.controls_builder.0.dart **
  /// {@end-tool}
  final ControlsWidgetBuilder? controlsBuilder;

  /// The elevation of this stepper's [Material] when [type] is [StepperType.horizontal].
  final double? elevation;

  /// Custom margin on vertical stepper.
  final EdgeInsetsGeometry? margin;

  /// Customize connected lines colors.
  ///
  /// Resolves in the following states:
  ///  * [WidgetState.selected].
  ///  * [WidgetState.disabled].
  ///
  /// If not set then the widget will use default colors, primary for selected state
  /// and grey.shade400 for disabled state.
  final WidgetStateProperty<Color>? connectorColor;

  /// The thickness of the connecting lines.
  final double? connectorThickness;

  /// Callback for creating custom icons for the [steps].
  ///
  /// When overriding icon for [StepState.error], please return
  /// a widget whose width and height are 14 pixels or less to avoid overflow.
  ///
  /// If null, the default icons will be used for respective [StepState].
  final StepIconBuilder? stepIconBuilder;

  /// Overrides the default step icon size height.
  final double? stepIconHeight;

  /// Overrides the default step icon size width.
  final double? stepIconWidth;

  /// Overrides the default step icon margin.
  final EdgeInsets? stepIconMargin;

  /// The [Step.content] will be clipped to this Clip type.
  ///
  /// Defaults to [Clip.none].
  ///
  /// See also:
  ///
  ///  * [Clip], which explains how to use this property.
  final Clip clipBehavior;

  /// The padding around the header row in both [StepperType.vertical] and
  /// [StepperType.horizontal] steppers.
  ///
  /// Defaults to to `EdgeInsets.symmetric(horizontal: 24.0)`.
  final EdgeInsetsGeometry? headerPadding;

  /// The padding around the content area in both [StepperType.vertical] and
  /// [StepperType.horizontal] steppers.
  ///
  /// For [StepperType.horizontal], defaults to `EdgeInsets.all(24.0)`.
  ///
  /// For [StepperType.vertical], defaults to
  /// `EdgeInsetsDirectional.only(start: 60.0, end: 24.0, bottom: 24.0)`.
  /// The `start` padding is also increased by the `left` value of
  /// [stepIconMargin] if it is provided.
  final EdgeInsetsGeometry? contentPadding;

  @override
  State<Stepper> createState() => _StepperState();
}

class _StepperState extends State<Stepper> with TickerProviderStateMixin {
  late List<GlobalKey> _keys;
  final Map<int, StepState> _oldStates = <int, StepState>{};

  @override
  void initState() {
    super.initState();
    _keys = List<GlobalKey>.generate(widget.steps.length, (int i) => GlobalKey());

    for (var i = 0; i < widget.steps.length; i += 1) {
      _oldStates[i] = widget.steps[i].state;
    }
  }

  @override
  void didUpdateWidget(Stepper oldWidget) {
    super.didUpdateWidget(oldWidget);
    assert(widget.steps.length == oldWidget.steps.length);

    for (var i = 0; i < oldWidget.steps.length; i += 1) {
      _oldStates[i] = oldWidget.steps[i].state;
    }
  }

  EdgeInsetsGeometry? get _stepIconMargin => widget.stepIconMargin;

  double? get _stepIconHeight => widget.stepIconHeight;

  double? get _stepIconWidth => widget.stepIconWidth;

  EdgeInsetsGeometry get effectiveHeaderPadding => widget.headerPadding ?? _kDefaultHeaderPadding;

  double get _heightFactor {
    return (_isLabel() && _stepIconHeight != null) ? 2.5 : 2.0;
  }

  bool _isFirst(int index) {
    return index == 0;
  }

  bool _isLast(int index) {
    return widget.steps.length - 1 == index;
  }

  bool _isCurrent(int index) {
    return widget.currentStep == index;
  }

  bool _isDark() {
    return Theme.brightnessOf(context) == Brightness.dark;
  }

  bool _isLabel() {
    return widget.steps.any((Step step) => step.label != null);
  }

  StepStyle? _stepStyle(int index) {
    return widget.steps[index].stepStyle;
  }

  Color _connectorColor(bool isActive) {
    final ColorScheme colorScheme = Theme.of(context).colorScheme;
    final states = <WidgetState>{if (isActive) WidgetState.selected else WidgetState.disabled};
    final Color? resolvedConnectorColor = widget.connectorColor?.resolve(states);

    return resolvedConnectorColor ?? (isActive ? colorScheme.primary : Colors.grey.shade400);
  }

  Widget _buildLine(bool visible, bool isActive) {
    return ColoredBox(
      color: _connectorColor(isActive),
      child: SizedBox(width: visible ? widget.connectorThickness ?? 1.0 : 0.0, height: 16.0),
    );
  }

  Widget _buildCircleChild(int index, bool oldState) {
    final StepState state = oldState ? _oldStates[index]! : widget.steps[index].state;
    if (widget.stepIconBuilder?.call(index, state) case final Widget icon) {
      return icon;
    }
    TextStyle? textStyle = _stepStyle(index)?.indexStyle;
    final bool isDarkActive = _isDark() && widget.steps[index].isActive;
    final Color iconColor = isDarkActive ? _kCircleActiveDark : _kCircleActiveLight;
    textStyle ??= isDarkActive ? _kStepStyle.copyWith(color: Colors.black87) : _kStepStyle;

    return switch (state) {
      StepState.indexed || StepState.disabled => Text('${index + 1}', style: textStyle),
      StepState.editing => Icon(Icons.edit, color: iconColor, size: 18.0),
      StepState.complete => Icon(Icons.check, color: iconColor, size: 18.0),
      StepState.error => const Center(child: Text('!', style: _kStepStyle)),
    };
  }

  Color _circleColor(int index) {
    final bool isActive = widget.steps[index].isActive;
    final ColorScheme colorScheme = Theme.of(context).colorScheme;
    final states = <WidgetState>{if (isActive) WidgetState.selected else WidgetState.disabled};
    final Color? resolvedConnectorColor = widget.connectorColor?.resolve(states);
    if (resolvedConnectorColor != null) {
      return resolvedConnectorColor;
    }
    if (!_isDark()) {
      return isActive ? colorScheme.primary : colorScheme.onSurface.withOpacity(0.38);
    } else {
      return isActive ? colorScheme.secondary : colorScheme.background;
    }
  }

  Widget _buildCircle(int index, bool oldState) {
    return Padding(
      padding: _stepIconMargin ?? const EdgeInsets.symmetric(vertical: 8.0),
      child: SizedBox(
        width: _stepIconWidth ?? _kStepSize,
        height: _stepIconHeight ?? _kStepSize,
        child: AnimatedContainer(
          curve: Curves.fastOutSlowIn,
          duration: kThemeAnimationDuration,
          decoration: BoxDecoration(
            color: _stepStyle(index)?.color ?? _circleColor(index),
            shape: BoxShape.circle,
            border: _stepStyle(index)?.border,
            boxShadow: _stepStyle(index)?.boxShadow != null
                ? <BoxShadow>[_stepStyle(index)!.boxShadow!]
                : null,
            gradient: _stepStyle(index)?.gradient,
          ),
          child: Center(
            child: _buildCircleChild(
              index,
              oldState && widget.steps[index].state == StepState.error,
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildTriangle(int index, bool oldState) {
    Color? color = _stepStyle(index)?.errorColor;
    color ??= _isDark() ? _kErrorDark : _kErrorLight;

    return Padding(
      padding: _stepIconMargin ?? const EdgeInsets.symmetric(vertical: 8.0),
      child: SizedBox(
        width: _stepIconWidth ?? _kStepSize,
        height: _stepIconHeight ?? _kStepSize,
        child: Center(
          child: SizedBox(
            width: _stepIconWidth ?? _kStepSize,
            height: _stepIconHeight != null ? _stepIconHeight! * _kTriangleSqrt : _kTriangleHeight,
            child: CustomPaint(
              painter: _TrianglePainter(color: color),
              child: Align(
                alignment: const Alignment(0.0, 0.8), // 0.8 looks better than the geometrical 0.33.
                child: _buildCircleChild(
                  index,
                  oldState && widget.steps[index].state != StepState.error,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildIcon(int index) {
    if (widget.steps[index].state != _oldStates[index]) {
      return AnimatedCrossFade(
        firstChild: _buildCircle(index, true),
        secondChild: _buildTriangle(index, true),
        firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
        secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
        sizeCurve: Curves.fastOutSlowIn,
        crossFadeState: widget.steps[index].state == StepState.error
            ? CrossFadeState.showSecond
            : CrossFadeState.showFirst,
        duration: kThemeAnimationDuration,
      );
    } else {
      if (widget.steps[index].state != StepState.error) {
        return _buildCircle(index, false);
      } else {
        return _buildTriangle(index, false);
      }
    }
  }

  Widget _buildVerticalControls(int stepIndex) {
    if (widget.controlsBuilder != null) {
      return widget.controlsBuilder!(
        context,
        ControlsDetails(
          currentStep: widget.currentStep,
          onStepContinue: widget.onStepContinue,
          onStepCancel: widget.onStepCancel,
          stepIndex: stepIndex,
        ),
      );
    }

    final Color cancelColor = switch (Theme.brightnessOf(context)) {
      Brightness.light => Colors.black54,
      Brightness.dark => Colors.white70,
    };

    final ThemeData themeData = Theme.of(context);
    final ColorScheme colorScheme = themeData.colorScheme;
    final MaterialLocalizations localizations = MaterialLocalizations.of(context);

    const OutlinedBorder buttonShape = RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(2)),
    );
    const buttonPadding = EdgeInsets.symmetric(horizontal: 16.0);

    return Padding(
      padding: const EdgeInsets.only(top: 16.0),
      child: SizedBox(
        height: 48.0,
        child: Row(
          // The Material spec no longer includes a Stepper widget. The continue
          // and cancel button styles have been configured to match the original
          // version of this widget.
          children: <Widget>[
            TextButton(
              onPressed: widget.onStepContinue,
              style: ButtonStyle(
                foregroundColor: WidgetStateProperty.resolveWith<Color?>((Set<WidgetState> states) {
                  return states.contains(WidgetState.disabled)
                      ? null
                      : (_isDark() ? colorScheme.onSurface : colorScheme.onPrimary);
                }),
                backgroundColor: WidgetStateProperty.resolveWith<Color?>((Set<WidgetState> states) {
                  return _isDark() || states.contains(WidgetState.disabled)
                      ? null
                      : colorScheme.primary;
                }),
                padding: const MaterialStatePropertyAll<EdgeInsetsGeometry>(buttonPadding),
                shape: const MaterialStatePropertyAll<OutlinedBorder>(buttonShape),
              ),
              child: Text(
                themeData.useMaterial3
                    ? localizations.continueButtonLabel
                    : localizations.continueButtonLabel.toUpperCase(),
              ),
            ),
            Padding(
              padding: const EdgeInsetsDirectional.only(start: 8.0),
              child: TextButton(
                onPressed: widget.onStepCancel,
                style: TextButton.styleFrom(
                  foregroundColor: cancelColor,
                  padding: buttonPadding,
                  shape: buttonShape,
                ),
                child: Text(
                  themeData.useMaterial3
                      ? localizations.cancelButtonLabel
                      : localizations.cancelButtonLabel.toUpperCase(),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  TextStyle _titleStyle(int index) {
    final ThemeData themeData = Theme.of(context);
    final TextTheme textTheme = themeData.textTheme;

    switch (widget.steps[index].state) {
      case StepState.indexed:
      case StepState.editing:
      case StepState.complete:
        return textTheme.bodyLarge!;
      case StepState.disabled:
        return textTheme.bodyLarge!.copyWith(color: _isDark() ? _kDisabledDark : _kDisabledLight);
      case StepState.error:
        return textTheme.bodyLarge!.copyWith(color: _isDark() ? _kErrorDark : _kErrorLight);
    }
  }

  TextStyle _subtitleStyle(int index) {
    final ThemeData themeData = Theme.of(context);
    final TextTheme textTheme = themeData.textTheme;

    switch (widget.steps[index].state) {
      case StepState.indexed:
      case StepState.editing:
      case StepState.complete:
        return textTheme.bodySmall!;
      case StepState.disabled:
        return textTheme.bodySmall!.copyWith(color: _isDark() ? _kDisabledDark : _kDisabledLight);
      case StepState.error:
        return textTheme.bodySmall!.copyWith(color: _isDark() ? _kErrorDark : _kErrorLight);
    }
  }

  TextStyle _labelStyle(int index) {
    final ThemeData themeData = Theme.of(context);
    final TextTheme textTheme = themeData.textTheme;

    switch (widget.steps[index].state) {
      case StepState.indexed:
      case StepState.editing:
      case StepState.complete:
        return textTheme.bodyLarge!;
      case StepState.disabled:
        return textTheme.bodyLarge!.copyWith(color: _isDark() ? _kDisabledDark : _kDisabledLight);
      case StepState.error:
        return textTheme.bodyLarge!.copyWith(color: _isDark() ? _kErrorDark : _kErrorLight);
    }
  }

  Widget _buildHeaderText(int index) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisSize: MainAxisSize.min,
      children: <Widget>[
        AnimatedDefaultTextStyle(
          style: _titleStyle(index),
          duration: kThemeAnimationDuration,
          curve: Curves.fastOutSlowIn,
          child: widget.steps[index].title,
        ),
        if (widget.steps[index].subtitle != null)
          Padding(
            padding: const EdgeInsets.only(top: 2.0),
            child: AnimatedDefaultTextStyle(
              style: _subtitleStyle(index),
              duration: kThemeAnimationDuration,
              curve: Curves.fastOutSlowIn,
              child: widget.steps[index].subtitle!,
            ),
          ),
      ],
    );
  }

  Widget _buildLabelText(int index) {
    if (widget.steps[index].label != null) {
      return AnimatedDefaultTextStyle(
        style: _labelStyle(index),
        duration: kThemeAnimationDuration,
        child: widget.steps[index].label!,
      );
    }
    return const SizedBox.shrink();
  }

  Widget _buildVerticalHeader(int index) {
    final bool isActive = widget.steps[index].isActive;
    final bool isPreviousActive = index > 0 && widget.steps[index - 1].isActive;
    return Padding(
      padding: effectiveHeaderPadding,
      child: Row(
        children: <Widget>[
          Column(
            children: <Widget>[
              // Line parts are always added in order for the ink splash to
              // flood the tips of the connector lines.
              _buildLine(!_isFirst(index), isPreviousActive),
              _buildIcon(index),
              _buildLine(!_isLast(index), isActive),
            ],
          ),
          Expanded(
            child: Padding(
              padding: const EdgeInsetsDirectional.only(start: 12.0),
              child: _buildHeaderText(index),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildVerticalBody(int index) {
    final double? marginLeft = _stepIconMargin?.resolve(TextDirection.ltr).left;
    final double? marginRight = _stepIconMargin?.resolve(TextDirection.ltr).right;
    final double? additionalMarginLeft = marginLeft != null ? marginLeft / 2.0 : null;
    final double? additionalMarginRight = marginRight != null ? marginRight / 2.0 : null;
    // Adjust vertical content padding to align with step icon when stepIconMargin is set.
    final EdgeInsetsGeometry effectiveVerticalContentPadding =
        (widget.contentPadding ?? _kDefaultVerticalContentPadding).add(
          EdgeInsetsDirectional.only(start: marginLeft ?? 0.0),
        );

    return Stack(
      children: <Widget>[
        PositionedDirectional(
          // When use margin affects the left or right side of the child, we
          // need to add half of the margin to the start or end of the child
          // respectively to get the correct positioning.
          start: 24.0 + (additionalMarginLeft ?? 0.0) + (additionalMarginRight ?? 0.0),
          top: 0.0,
          bottom: 0.0,
          width: _stepIconWidth ?? _kStepSize,
          child: Center(
            // The line is drawn from the center of the circle vertically until
            // it reaches the bottom and then horizontally to the edge of the
            // stepper.
            child: SizedBox(
              width: !_isLast(index) ? (widget.connectorThickness ?? 1.0) : 0.0,
              height: double.infinity,
              child: ColoredBox(color: _connectorColor(widget.steps[index].isActive)),
            ),
          ),
        ),
        AnimatedCrossFade(
          firstChild: const SizedBox(width: double.infinity, height: 0),
          secondChild: Padding(
            padding: effectiveVerticalContentPadding,
            child: Column(
              children: <Widget>[
                ClipRect(clipBehavior: widget.clipBehavior, child: widget.steps[index].content),
                _buildVerticalControls(index),
              ],
            ),
          ),
          firstCurve: const Interval(0.0, 0.6, curve: Curves.fastOutSlowIn),
          secondCurve: const Interval(0.4, 1.0, curve: Curves.fastOutSlowIn),
          sizeCurve: Curves.fastOutSlowIn,
          crossFadeState: _isCurrent(index) ? CrossFadeState.showSecond : CrossFadeState.showFirst,
          duration: kThemeAnimationDuration,
        ),
      ],
    );
  }

  Widget _buildVertical() {
    return ListView(
      controller: widget.controller,
      shrinkWrap: true,
      physics: widget.physics,
      children: <Widget>[
        for (int i = 0; i < widget.steps.length; i += 1)
          Column(
            key: _keys[i],
            children: <Widget>[
              InkWell(
                onTap: widget.steps[i].state != StepState.disabled
                    ? () {
                        // In the vertical case we need to scroll to the newly tapped
                        // step.
                        Scrollable.ensureVisible(
                          _keys[i].currentContext!,
                          curve: Curves.fastOutSlowIn,
                          duration: kThemeAnimationDuration,
                        );

                        widget.onStepTapped?.call(i);
                      }
                    : null,
                canRequestFocus: widget.steps[i].state != StepState.disabled,
                child: _buildVerticalHeader(i),
              ),
              _buildVerticalBody(i),
            ],
          ),
      ],
    );
  }

  Widget _buildHorizontal() {
    // Effective horizontal content padding (custom or default).
    final EdgeInsetsGeometry effectiveHorizontalContentPadding =
        widget.contentPadding ?? _kDefaultHorizontalContentPadding;

    final children = <Widget>[
      for (int i = 0; i < widget.steps.length; i += 1) ...<Widget>[
        InkResponse(
          onTap: widget.steps[i].state != StepState.disabled
              ? () {
                  widget.onStepTapped?.call(i);
                }
              : null,
          canRequestFocus: widget.steps[i].state != StepState.disabled,
          child: Row(
            children: <Widget>[
              SizedBox(
                height: _isLabel() ? 104.0 : 72.0,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    if (widget.steps[i].label != null) const SizedBox(height: 24.0),
                    Center(child: _buildIcon(i)),
                    if (widget.steps[i].label != null)
                      SizedBox(height: 24.0, child: _buildLabelText(i)),
                  ],
                ),
              ),
              Padding(
                padding: _stepIconMargin ?? const EdgeInsetsDirectional.only(start: 12.0),
                child: _buildHeaderText(i),
              ),
            ],
          ),
        ),
        if (!_isLast(i))
          Expanded(
            child: Padding(
              padding: _stepIconMargin ?? const EdgeInsets.symmetric(horizontal: 8.0),
              child: SizedBox(
                height:
                    widget.steps[i].stepStyle?.connectorThickness ??
                    widget.connectorThickness ??
                    1.0,
                child: ColoredBox(
                  color:
                      widget.steps[i].stepStyle?.connectorColor ??
                      _connectorColor(widget.steps[i].isActive),
                ),
              ),
            ),
          ),
      ],
    ];

    final stepPanels = <Widget>[];
    for (var i = 0; i < widget.steps.length; i += 1) {
      stepPanels.add(
        Visibility(
          maintainState: true,
          visible: i == widget.currentStep,
          child: ClipRect(clipBehavior: widget.clipBehavior, child: widget.steps[i].content),
        ),
      );
    }

    return Column(
      children: <Widget>[
        Material(
          elevation: widget.elevation ?? 2,
          child: Padding(
            padding: effectiveHeaderPadding,
            child: SizedBox(
              height: _stepIconHeight != null ? _stepIconHeight! * _heightFactor : null,
              child: Row(children: children),
            ),
          ),
        ),
        Expanded(
          child: ListView(
            controller: widget.controller,
            physics: widget.physics,
            padding: effectiveHorizontalContentPadding,
            children: <Widget>[
              AnimatedSize(
                curve: Curves.fastOutSlowIn,
                duration: kThemeAnimationDuration,
                child: Column(crossAxisAlignment: CrossAxisAlignment.stretch, children: stepPanels),
              ),
              _buildVerticalControls(widget.currentStep),
            ],
          ),
        ),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMaterial(context));
    assert(debugCheckHasMaterialLocalizations(context));
    assert(() {
      if (context.findAncestorWidgetOfExactType<Stepper>() != null) {
        throw FlutterError(
          'Steppers must not be nested.\n'
          'The material specification advises that one should avoid embedding '
          'steppers within steppers. '
          'https://material.io/archive/guidelines/components/steppers.html#steppers-usage',
        );
      }
      return true;
    }());
    return switch (widget.type) {
      StepperType.vertical => _buildVertical(),
      StepperType.horizontal => _buildHorizontal(),
    };
  }
}

// Paints a triangle whose base is the bottom of the bounding rectangle and its
// top vertex the middle of its top.
class _TrianglePainter extends CustomPainter {
  _TrianglePainter({required this.color});

  final Color color;

  @override
  bool hitTest(Offset point) => true; // Hitting the rectangle is fine enough.

  @override
  bool shouldRepaint(_TrianglePainter oldPainter) {
    return oldPainter.color != color;
  }

  @override
  void paint(Canvas canvas, Size size) {
    final double base = size.width;
    final double halfBase = size.width / 2.0;
    final double height = size.height;
    final points = <Offset>[Offset(0.0, height), Offset(base, height), Offset(halfBase, 0.0)];

    canvas.drawPath(Path()..addPolygon(points, true), Paint()..color = color);
  }
}

/// This class is used to override the default visual properties of [Step] widgets within a [Stepper].
///
/// To customize the appearance of a [Step] create an instance of this class with non-null parameters
/// for the step properties whose default value you want to override.
///
/// Example usage:
/// ```dart
/// Step(
///   title: const Text('Step 1'),
///   content: const Text('Content for Step 1'),
///   stepStyle: StepStyle(
///     color: Colors.blue,
///     errorColor: Colors.red,
///     border: Border.all(color: Colors.grey),
///     boxShadow: const BoxShadow(blurRadius: 3.0, color: Colors.black26),
///     gradient: const LinearGradient(colors: <Color>[Colors.red, Colors.blue]),
///     indexStyle: const TextStyle(color: Colors.white),
///   ),
/// )
/// ```
///
/// {@tool dartpad}
/// An example that uses [StepStyle] to customize the appearance of each [Step] in a [Stepper].
///
/// ** See code in examples/api/lib/material/stepper/step_style.0.dart **
/// {@end-tool}

@immutable
class StepStyle with Diagnosticable {
  /// Constructs a [StepStyle].
  const StepStyle({
    this.color,
    this.errorColor,
    this.connectorColor,
    this.connectorThickness,
    this.border,
    this.boxShadow,
    this.gradient,
    this.indexStyle,
  });

  /// Overrides the default color of the circle in the step.
  final Color? color;

  /// Overrides the default color of the error indicator in the step.
  final Color? errorColor;

  /// Overrides the default color of the connector line between two steps.
  ///
  /// This property only applies when [Stepper.type] is [StepperType.horizontal].
  final Color? connectorColor;

  /// Overrides the default thickness of the connector line between two steps.
  ///
  /// This property only applies when [Stepper.type] is [StepperType.horizontal].
  final double? connectorThickness;

  /// Add a border around the step.
  ///
  /// Will be applied to the circle in the step.
  final BoxBorder? border;

  /// Add a shadow around the step.
  final BoxShadow? boxShadow;

  /// Add a gradient around the step.
  ///
  /// If [gradient] is specified, [color] will be ignored.
  final Gradient? gradient;

  /// Overrides the default style of the index in the step.
  final TextStyle? indexStyle;

  /// Returns a copy of this ButtonStyle with the given fields replaced with
  /// the new values.
  StepStyle copyWith({
    Color? color,
    Color? errorColor,
    Color? connectorColor,
    double? connectorThickness,
    BoxBorder? border,
    BoxShadow? boxShadow,
    Gradient? gradient,
    TextStyle? indexStyle,
  }) {
    return StepStyle(
      color: color ?? this.color,
      errorColor: errorColor ?? this.errorColor,
      connectorColor: connectorColor ?? this.connectorColor,
      connectorThickness: connectorThickness ?? this.connectorThickness,
      border: border ?? this.border,
      boxShadow: boxShadow ?? this.boxShadow,
      gradient: gradient ?? this.gradient,
      indexStyle: indexStyle ?? this.indexStyle,
    );
  }

  /// Returns a copy of this StepStyle where the non-null fields in [stepStyle]
  /// have replaced the corresponding null fields in this StepStyle.
  ///
  /// In other words, [stepStyle] is used to fill in unspecified (null) fields
  /// this StepStyle.
  StepStyle merge(StepStyle? stepStyle) {
    if (stepStyle == null) {
      return this;
    }
    return copyWith(
      color: stepStyle.color,
      errorColor: stepStyle.errorColor,
      connectorColor: stepStyle.connectorColor,
      connectorThickness: stepStyle.connectorThickness,
      border: stepStyle.border,
      boxShadow: stepStyle.boxShadow,
      gradient: stepStyle.gradient,
      indexStyle: stepStyle.indexStyle,
    );
  }

  @override
  int get hashCode {
    return Object.hash(
      color,
      errorColor,
      connectorColor,
      connectorThickness,
      border,
      boxShadow,
      gradient,
      indexStyle,
    );
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is StepStyle &&
        other.color == color &&
        other.errorColor == errorColor &&
        other.connectorColor == connectorColor &&
        other.connectorThickness == connectorThickness &&
        other.border == border &&
        other.boxShadow == boxShadow &&
        other.gradient == gradient &&
        other.indexStyle == indexStyle;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    final theme = ThemeData.fallback();
    final TextTheme defaultTextTheme = theme.textTheme;
    properties.add(ColorProperty('color', color, defaultValue: null));
    properties.add(ColorProperty('errorColor', errorColor, defaultValue: null));
    properties.add(ColorProperty('connectorColor', connectorColor, defaultValue: null));
    properties.add(DoubleProperty('connectorThickness', connectorThickness, defaultValue: null));
    properties.add(DiagnosticsProperty<BoxBorder>('border', border, defaultValue: null));
    properties.add(DiagnosticsProperty<BoxShadow>('boxShadow', boxShadow, defaultValue: null));
    properties.add(DiagnosticsProperty<Gradient>('gradient', gradient, defaultValue: null));
    properties.add(
      DiagnosticsProperty<TextStyle>(
        'indexStyle',
        indexStyle,
        defaultValue: defaultTextTheme.bodyLarge,
      ),
    );
  }
}
