// 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 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import 'theme.dart';

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

/// Defines the configuration of the search views created by the [SearchAnchor]
/// widget.
///
/// Descendant widgets obtain the current [SearchViewThemeData] object using
/// `SearchViewTheme.of(context)`.
///
/// Typically, a [SearchViewThemeData] is specified as part of the overall [Theme]
/// with [ThemeData.searchViewTheme]. Otherwise, [SearchViewTheme] can be used
/// to configure its own widget subtree.
///
/// All [SearchViewThemeData] properties are `null` by default. If any of these
/// properties are null, the search view will provide its own defaults.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme for the application.
/// * [SearchBarThemeData], which describes the theme for the search bar itself in a
///   [SearchBar] widget.
/// * [SearchAnchor], which is used to open a search view route.
@immutable
class SearchViewThemeData with Diagnosticable {
  /// Creates a theme that can be used for [ThemeData.searchViewTheme].
  const SearchViewThemeData({
    this.backgroundColor,
    this.elevation,
    this.surfaceTintColor,
    this.constraints,
    this.side,
    this.shape,
    this.headerTextStyle,
    this.headerHintStyle,
    this.dividerColor,
  });

  /// Overrides the default value of the [SearchAnchor.viewBackgroundColor].
  final Color? backgroundColor;

  /// Overrides the default value of the [SearchAnchor.viewElevation].
  final double? elevation;

  /// Overrides the default value of the [SearchAnchor.viewSurfaceTintColor].
  final Color? surfaceTintColor;

  /// Overrides the default value of the [SearchAnchor.viewSide].
  final BorderSide? side;

  /// Overrides the default value of the [SearchAnchor.viewShape].
  final OutlinedBorder? shape;

  /// Overrides the default value for [SearchAnchor.headerTextStyle].
  final TextStyle? headerTextStyle;

  /// Overrides the default value for [SearchAnchor.headerHintStyle].
  final TextStyle? headerHintStyle;

  /// Overrides the value of size constraints for [SearchAnchor.viewConstraints].
  final BoxConstraints? constraints;

  /// Overrides the value of the divider color for [SearchAnchor.dividerColor].
  final Color? dividerColor;

  /// Creates a copy of this object but with the given fields replaced with the
  /// new values.
  SearchViewThemeData copyWith({
    Color? backgroundColor,
    double? elevation,
    Color? surfaceTintColor,
    BorderSide? side,
    OutlinedBorder? shape,
    TextStyle? headerTextStyle,
    TextStyle? headerHintStyle,
    BoxConstraints? constraints,
    Color? dividerColor,
  }) {
    return SearchViewThemeData(
      backgroundColor: backgroundColor ?? this.backgroundColor,
      elevation: elevation ?? this.elevation,
      surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
      side: side ?? this.side,
      shape: shape ?? this.shape,
      headerTextStyle: headerTextStyle ?? this.headerTextStyle,
      headerHintStyle: headerHintStyle ?? this.headerHintStyle,
      constraints: constraints ?? this.constraints,
      dividerColor: dividerColor ?? this.dividerColor,
    );
  }

  /// Linearly interpolate between two [SearchViewThemeData]s.
  static SearchViewThemeData? lerp(SearchViewThemeData? a, SearchViewThemeData? b, double t) {
    if (identical(a, b)) {
      return a;
    }
    return SearchViewThemeData(
      backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
      elevation: lerpDouble(a?.elevation, b?.elevation, t),
      surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
      side: _lerpSides(a?.side, b?.side, t),
      shape: OutlinedBorder.lerp(a?.shape, b?.shape, t),
      headerTextStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
      headerHintStyle: TextStyle.lerp(a?.headerTextStyle, b?.headerTextStyle, t),
      constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
      dividerColor: Color.lerp(a?.dividerColor, b?.dividerColor, t),
    );
  }

  @override
  int get hashCode => Object.hash(
    backgroundColor,
    elevation,
    surfaceTintColor,
    side,
    shape,
    headerTextStyle,
    headerHintStyle,
    constraints,
    dividerColor,
  );

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is SearchViewThemeData
      && other.backgroundColor == backgroundColor
      && other.elevation == elevation
      && other.surfaceTintColor == surfaceTintColor
      && other.side == side
      && other.shape == shape
      && other.headerTextStyle == headerTextStyle
      && other.headerHintStyle == headerHintStyle
      && other.constraints == constraints
      && other.dividerColor == dividerColor;
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<Color?>('backgroundColor', backgroundColor, defaultValue: null));
    properties.add(DiagnosticsProperty<double?>('elevation', elevation, defaultValue: null));
    properties.add(DiagnosticsProperty<Color?>('surfaceTintColor', surfaceTintColor, defaultValue: null));
    properties.add(DiagnosticsProperty<BorderSide?>('side', side, defaultValue: null));
    properties.add(DiagnosticsProperty<OutlinedBorder?>('shape', shape, defaultValue: null));
    properties.add(DiagnosticsProperty<TextStyle?>('headerTextStyle', headerTextStyle, defaultValue: null));
    properties.add(DiagnosticsProperty<TextStyle?>('headerHintStyle', headerHintStyle, defaultValue: null));
    properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
    properties.add(DiagnosticsProperty<Color?>('dividerColor', dividerColor, defaultValue: null));
  }

  // Special case because BorderSide.lerp() doesn't support null arguments
  static BorderSide? _lerpSides(BorderSide? a, BorderSide? b, double t) {
    if (a == null || b == null) {
      return null;
    }
    if (identical(a, b)) {
      return a;
    }
    return BorderSide.lerp(a, b, t);
  }
}

/// An inherited widget that defines the configuration in this widget's
/// descendants for search view created by the [SearchAnchor] widget.
///
/// A search view theme can be specified as part of the overall Material theme using
/// [ThemeData.searchViewTheme].
///
/// See also:
///
///  * [SearchViewThemeData], which describes the actual configuration of a search view
///    theme.
class SearchViewTheme extends InheritedWidget {
  /// Creates a const theme that controls the configurations for the search view
  /// created by the [SearchAnchor] widget.
  const SearchViewTheme({
    super.key,
    required this.data,
    required super.child,
  });

  /// The properties used for all descendant [SearchAnchor] widgets.
  final SearchViewThemeData data;

  /// Returns the configuration [data] from the closest [SearchViewTheme] ancestor.
  /// If there is no ancestor, it returns [ThemeData.searchViewTheme].
  ///
  /// Typical usage is as follows:
  ///
  /// ```dart
  /// SearchViewThemeData theme = SearchViewTheme.of(context);
  /// ```
  static SearchViewThemeData of(BuildContext context) {
    final SearchViewTheme? searchViewTheme = context.dependOnInheritedWidgetOfExactType<SearchViewTheme>();
    return searchViewTheme?.data ?? Theme.of(context).searchViewTheme;
  }

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