// 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/cupertino.dart';
import 'package:flutter/foundation.dart';

import 'input_decorator.dart';
import 'menu_style.dart';
import 'theme.dart';

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

/// Overrides the default values of visual properties for descendant [DropdownMenu] widgets.
///
/// Descendant widgets obtain the current [DropdownMenuThemeData] object with
/// [DropdownMenuTheme.of]. Instances of [DropdownMenuTheme] can
/// be customized with [DropdownMenuThemeData.copyWith].
///
/// Typically a [DropdownMenuTheme] is specified as part of the overall [Theme] with
/// [ThemeData.dropdownMenuTheme].
///
/// All [DropdownMenuThemeData] properties are null by default. When null, the [DropdownMenu]
/// computes its own default values, typically based on the overall
/// theme's [ThemeData.colorScheme], [ThemeData.textTheme], and [ThemeData.iconTheme].
@immutable
class DropdownMenuThemeData with Diagnosticable {
  /// Creates a [DropdownMenuThemeData] that can be used to override default properties
  /// in a [DropdownMenuTheme] widget.
  const DropdownMenuThemeData({
    this.textStyle,
    this.inputDecorationTheme,
    this.menuStyle,
  });

  /// Overrides the default value for [DropdownMenu.textStyle].
  final TextStyle? textStyle;

  /// The input decoration theme for the [TextField]s in a [DropdownMenu].
  ///
  /// If this is null, the [DropdownMenu] provides its own defaults.
  final InputDecorationTheme? inputDecorationTheme;

  /// Overrides the menu's default style in a [DropdownMenu].
  ///
  /// Any values not set in the [MenuStyle] will use the menu default for that
  /// property.
  final MenuStyle? menuStyle;

  /// Creates a copy of this object with the given fields replaced with the
  /// new values.
  DropdownMenuThemeData copyWith({
    TextStyle? textStyle,
    InputDecorationTheme? inputDecorationTheme,
    MenuStyle? menuStyle,
  }) {
    return DropdownMenuThemeData(
      textStyle: textStyle ?? this.textStyle,
      inputDecorationTheme: inputDecorationTheme ?? this.inputDecorationTheme,
      menuStyle: menuStyle ?? this.menuStyle,
    );
  }

  /// Linearly interpolates between two dropdown menu themes.
  static DropdownMenuThemeData lerp(DropdownMenuThemeData? a, DropdownMenuThemeData? b, double t) {
    return DropdownMenuThemeData(
      textStyle: TextStyle.lerp(a?.textStyle, b?.textStyle, t),
      inputDecorationTheme: t < 0.5 ? a?.inputDecorationTheme : b?.inputDecorationTheme,
      menuStyle: MenuStyle.lerp(a?.menuStyle, b?.menuStyle, t),
    );
  }

  @override
  int get hashCode => Object.hash(
    textStyle,
    inputDecorationTheme,
    menuStyle,
  );

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

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<TextStyle>('textStyle', textStyle, defaultValue: null));
    properties.add(DiagnosticsProperty<InputDecorationTheme>('inputDecorationTheme', inputDecorationTheme, defaultValue: null));
    properties.add(DiagnosticsProperty<MenuStyle>('menuStyle', menuStyle, defaultValue: null));
  }
}

/// An inherited widget that defines the visual properties for [DropdownMenu]s in this widget's subtree.
///
/// Values specified here are used for [DropdownMenu] properties that are not
/// given an explicit non-null value.
class DropdownMenuTheme extends InheritedTheme {
  /// Creates a [DropdownMenuTheme] that controls visual parameters for
  /// descendant [DropdownMenu]s.
  const DropdownMenuTheme({
    super.key,
    required this.data,
    required super.child,
  });

  /// Specifies the visual properties used by descendant [DropdownMenu]
  /// widgets.
  final DropdownMenuThemeData data;

  /// The closest instance of this class that encloses the given context.
  ///
  /// If there is no enclosing [DropdownMenuTheme] widget, then
  /// [ThemeData.dropdownMenuTheme] is used.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// DropdownMenuThemeData theme = DropdownMenuTheme.of(context);
  /// ```
  ///
  /// See also:
  ///
  ///  * [maybeOf], which returns null if it doesn't find a
  ///    [DropdownMenuTheme] ancestor.
  static DropdownMenuThemeData of(BuildContext context) {
    return maybeOf(context) ?? Theme.of(context).dropdownMenuTheme;
  }

  /// The data from the closest instance of this class that encloses the given
  /// context, if any.
  ///
  /// Use this function if you want to allow situations where no
  /// [DropdownMenuTheme] is in scope. Prefer using [DropdownMenuTheme.of]
  /// in situations where a [DropdownMenuThemeData] is expected to be
  /// non-null.
  ///
  /// If there is no [DropdownMenuTheme] in scope, then this function will
  /// return null.
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// DropdownMenuThemeData? theme = DropdownMenuTheme.maybeOf(context);
  /// if (theme == null) {
  ///   // Do something else instead.
  /// }
  /// ```
  ///
  /// See also:
  ///
  ///  * [of], which will return [ThemeData.dropdownMenuTheme] if it doesn't
  ///    find a [DropdownMenuTheme] ancestor, instead of returning null.
  static DropdownMenuThemeData? maybeOf(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<DropdownMenuTheme>()?.data;
  }

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

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