// 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,
  });

  /// 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;
}
