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

/// Mixin for [State] classes that require knowledge of changing [MaterialState]
/// values for their child widgets.
///
/// This mixin does nothing by mere application to a [State] class, but is
/// helpful when writing `build` methods that include child [InkWell],
/// [GestureDetector], [MouseRegion], or [Focus] widgets. Instead of manually
/// creating handlers for each type of user interaction, such [State] classes can
/// instead provide a `ValueChanged<bool>` function and allow [MaterialStateMixin]
/// to manage the set of active [MaterialState]s, and the calling of [setState]
/// as necessary.
///
/// {@tool snippet}
/// This example shows how to write a [StatefulWidget] that uses the
/// [MaterialStateMixin] class to watch [MaterialState] values.
///
/// ```dart
/// class MyWidget extends StatefulWidget {
///   const MyWidget({super.key, required this.color, required this.child});
///
///   final MaterialStateColor color;
///   final Widget child;
///
///   @override
///   State<MyWidget> createState() => MyWidgetState();
/// }
///
/// class MyWidgetState extends State<MyWidget> with MaterialStateMixin<MyWidget> {
///   @override
///   Widget build(BuildContext context) {
///     return InkWell(
///       onFocusChange: updateMaterialState(MaterialState.focused),
///       child: ColoredBox(
///         color: widget.color.resolve(materialStates),
///         child: widget.child,
///       ),
///     );
///   }
/// }
/// ```
/// {@end-tool}
@optionalTypeArgs
mixin MaterialStateMixin<T extends StatefulWidget> on State<T> {
  /// Managed set of active [MaterialState] values; designed to be passed to
  /// [MaterialStateProperty.resolve] methods.
  ///
  /// To mutate and have [setState] called automatically for you, use
  /// [setMaterialState], [addMaterialState], or [removeMaterialState]. Directly
  /// mutating the set is possible, and may be necessary if you need to alter its
  /// list without calling [setState] (and thus triggering a re-render).
  ///
  /// To check for a single condition, convenience getters [isPressed], [isHovered],
  /// [isFocused], etc, are available for each [MaterialState] value.
  @protected
  Set<MaterialState> materialStates = <MaterialState>{};

  /// Callback factory which accepts a [MaterialState] value and returns a
  /// closure to mutate [materialStates] and call [setState].
  ///
  /// Accepts an optional second named parameter, `onChanged`, which allows
  /// arbitrary functionality to be wired through the [MaterialStateMixin].
  /// If supplied, the [onChanged] function is only called when child widgets
  /// report events that make changes to the current set of [MaterialState]s.
  ///
  /// {@tool snippet}
  /// This example shows how to use the [updateMaterialState] callback factory
  /// in other widgets, including the optional [onChanged] callback.
  ///
  /// ```dart
  /// class MyWidget extends StatefulWidget {
  ///   const MyWidget({super.key, this.onPressed});
  ///
  ///   /// Something important this widget must do when pressed.
  ///   final VoidCallback? onPressed;
  ///
  ///   @override
  ///   State<MyWidget> createState() => MyWidgetState();
  /// }
  ///
  /// class MyWidgetState extends State<MyWidget> with MaterialStateMixin<MyWidget> {
  ///   @override
  ///   Widget build(BuildContext context) {
  ///     return ColoredBox(
  ///       color: isPressed ? Colors.black : Colors.white,
  ///       child: InkWell(
  ///         onHighlightChanged: updateMaterialState(
  ///           MaterialState.pressed,
  ///           onChanged: (bool val) {
  ///             if (val) {
  ///               widget.onPressed?.call();
  ///             }
  ///           },
  ///         ),
  ///       ),
  ///     );
  ///   }
  /// }
  /// ```
  /// {@end-tool}
  @protected
  ValueChanged<bool> updateMaterialState(MaterialState key, {ValueChanged<bool>? onChanged}) {
    return (bool value) {
      if (materialStates.contains(key) == value) {
        return;
      }
      setMaterialState(key, value);
      onChanged?.call(value);
    };
  }

  /// Mutator to mark a [MaterialState] value as either active or inactive.
  @protected
  void setMaterialState(MaterialState state, bool isSet) {
    return isSet ? addMaterialState(state) : removeMaterialState(state);
  }

  /// Mutator to mark a [MaterialState] value as active.
  @protected
  void addMaterialState(MaterialState state) {
    if (materialStates.add(state)) {
      setState((){});
    }
  }

  /// Mutator to mark a [MaterialState] value as inactive.
  @protected
  void removeMaterialState(MaterialState state) {
    if (materialStates.remove(state)) {
      setState((){});
    }
  }

  /// Getter for whether this class considers [MaterialState.disabled] to be active.
  bool get isDisabled => materialStates.contains(MaterialState.disabled);

  /// Getter for whether this class considers [MaterialState.dragged] to be active.
  bool get isDragged => materialStates.contains(MaterialState.dragged);

  /// Getter for whether this class considers [MaterialState.error] to be active.
  bool get isErrored => materialStates.contains(MaterialState.error);

  /// Getter for whether this class considers [MaterialState.focused] to be active.
  bool get isFocused => materialStates.contains(MaterialState.focused);

  /// Getter for whether this class considers [MaterialState.hovered] to be active.
  bool get isHovered => materialStates.contains(MaterialState.hovered);

  /// Getter for whether this class considers [MaterialState.pressed] to be active.
  bool get isPressed => materialStates.contains(MaterialState.pressed);

  /// Getter for whether this class considers [MaterialState.scrolledUnder] to be active.
  bool get isScrolledUnder => materialStates.contains(MaterialState.scrolledUnder);

  /// Getter for whether this class considers [MaterialState.selected] to be active.
  bool get isSelected => materialStates.contains(MaterialState.selected);

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Set<MaterialState>>('materialStates', materialStates, defaultValue: <MaterialState>{}));
  }
}
