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

// Examples can assume:
// late BuildContext context;

/// A [ButtonStyle] theme that overrides the default appearance of
/// [SubmenuButton]s and [MenuItemButton]s when it's used with a
/// [MenuButtonTheme] or with the overall [Theme]'s [ThemeData.menuTheme].
///
/// The [style]'s properties override [MenuItemButton]'s and [SubmenuButton]'s
/// default style, i.e. the [ButtonStyle] returned by
/// [MenuItemButton.defaultStyleOf] and [SubmenuButton.defaultStyleOf]. Only the
/// style's non-null property values or resolved non-null
/// [MaterialStateProperty] values are used.
///
/// See also:
///
/// * [MenuButtonTheme], the theme which is configured with this class.
/// * [MenuTheme], the theme used to configure the look of the menus these
///   buttons reside in.
/// * [MenuItemButton.defaultStyleOf] and [SubmenuButton.defaultStyleOf] which
///   return the default [ButtonStyle]s for menu buttons.
/// * [MenuItemButton.styleFrom] and [SubmenuButton.styleFrom], which converts
///   simple values into a [ButtonStyle] that's consistent with their respective
///   defaults.
/// * [MaterialStateProperty.resolve], "resolve" a material state property to a
///   simple value based on a set of [MaterialState]s.
/// * [ThemeData.menuButtonTheme], which can be used to override the default
///   [ButtonStyle] for [MenuItemButton]s and [SubmenuButton]s below the overall
///   [Theme].
/// * [MenuAnchor], a widget which hosts cascading menus.
/// * [MenuBar], a widget which defines a menu bar of buttons hosting cascading
///   menus.
@immutable
class MenuButtonThemeData with Diagnosticable {
  /// Creates a [MenuButtonThemeData].
  ///
  /// The [style] may be null.
  const MenuButtonThemeData({this.style});

  /// Overrides for [SubmenuButton] and [MenuItemButton]'s default style.
  ///
  /// Non-null properties or non-null resolved [MaterialStateProperty] values
  /// override the [ButtonStyle] returned by [SubmenuButton.defaultStyleOf] or
  /// [MenuItemButton.defaultStyleOf].
  ///
  /// If [style] is null, then this theme doesn't override anything.
  final ButtonStyle? style;

  /// Linearly interpolate between two menu button themes.
  static MenuButtonThemeData? lerp(MenuButtonThemeData? a, MenuButtonThemeData? b, double t) {
    return MenuButtonThemeData(style: ButtonStyle.lerp(a?.style, b?.style, t));
  }

  @override
  int get hashCode => style.hashCode;

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is MenuButtonThemeData && other.style == style;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<ButtonStyle>('style', style, defaultValue: null));
  }
}

/// Overrides the default [ButtonStyle] of its [MenuItemButton] and
/// [SubmenuButton] descendants.
///
/// See also:
///
/// * [MenuButtonThemeData], which is used to configure this theme.
/// * [MenuTheme], the theme used to configure the look of the menus themselves.
/// * [MenuItemButton.defaultStyleOf] and [SubmenuButton.defaultStyleOf] which
///   return the default [ButtonStyle]s for menu buttons.
/// * [MenuItemButton.styleFrom] and [SubmenuButton.styleFrom], which converts
///   simple values into a [ButtonStyle] that's consistent with their respective
///   defaults.
/// * [ThemeData.menuButtonTheme], which can be used to override the default
///   [ButtonStyle] for [MenuItemButton]s and [SubmenuButton]s below the overall
///   [Theme].
class MenuButtonTheme extends InheritedTheme {
  /// Create a [MenuButtonTheme].
  ///
  /// The [data] parameter must not be null.
  const MenuButtonTheme({
    super.key,
    required this.data,
    required super.child,
  }) : assert(data != null);

  /// The configuration of this theme.
  final MenuButtonThemeData data;

  /// The closest instance of this class that encloses the given context.
  ///
  /// If there is no enclosing [MenuButtonTheme] widget, then
  /// [ThemeData.menuButtonTheme] is used.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// MenuButtonThemeData theme = MenuButtonTheme.of(context);
  /// ```
  static MenuButtonThemeData of(BuildContext context) {
    final MenuButtonTheme? buttonTheme = context.dependOnInheritedWidgetOfExactType<MenuButtonTheme>();
    return buttonTheme?.data ?? Theme.of(context).menuButtonTheme;
  }

  @override
  Widget wrap(BuildContext context, Widget child) {
    return MenuButtonTheme(data: data, child: child);
  }

  @override
  bool updateShouldNotify(MenuButtonTheme oldWidget) => data != oldWidget.data;
}
