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

// Examples can assume:
// TooltipThemeData data = const TooltipThemeData();

/// An [InheritedWidget] that defines visual properties like colors
/// and text styles, which the [child]'s subtree depends on.
///
/// The [wrap] method is used by [captureAll] and [CapturedThemes.wrap] to
/// construct a widget that will wrap a child in all of the inherited themes
/// which are present in a specified part of the widget tree.
///
/// A widget that's shown in a different context from the one it's built in,
/// like the contents of a new route or an overlay, will be able to see the
/// ancestor inherited themes of the context it was built in.
///
/// {@tool dartpad}
/// This example demonstrates how `InheritedTheme.capture()` can be used
/// to wrap the contents of a new route with the inherited themes that
/// are present when the route was built - but are not present when route
/// is actually shown.
///
/// If the same code is run without `InheritedTheme.capture(), the
/// new route's Text widget will inherit the "something must be wrong"
/// fallback text style, rather than the default text style defined in MyApp.
///
/// ** See code in examples/api/lib/widgets/inherited_theme/inherited_theme.0.dart **
/// {@end-tool}
abstract class InheritedTheme extends InheritedWidget {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.

  const InheritedTheme({
    super.key,
    required super.child,
  });

  /// Return a copy of this inherited theme with the specified [child].
  ///
  /// This implementation for [TooltipTheme] is typical:
  ///
  /// ```dart
  /// Widget wrap(BuildContext context, Widget child) {
  ///   return TooltipTheme(data: data, child: child);
  /// }
  /// ```
  Widget wrap(BuildContext context, Widget child);

  /// Returns a widget that will [wrap] `child` in all of the inherited themes
  /// which are present between `context` and the specified `to`
  /// [BuildContext].
  ///
  /// The `to` context must be an ancestor of `context`. If `to` is not
  /// specified, all inherited themes up to the root of the widget tree are
  /// captured.
  ///
  /// After calling this method, the themes present between `context` and `to`
  /// are frozen for the provided `child`. If the themes (or their theme data)
  /// change in the original subtree, those changes will not be visible to
  /// the wrapped `child` - unless this method is called again to re-wrap the
  /// child.
  static Widget captureAll(BuildContext context, Widget child, {BuildContext? to}) {
    assert(child != null);
    assert(context != null);

    return capture(from: context, to: to).wrap(child);
  }

  /// Returns a [CapturedThemes] object that includes all the [InheritedTheme]s
  /// between the given `from` and `to` [BuildContext]s.
  ///
  /// The `to` context must be an ancestor of the `from` context. If `to` is
  /// null, all ancestor inherited themes of `from` up to the root of the
  /// widget tree are captured.
  ///
  /// After calling this method, the themes present between `from` and `to` are
  /// frozen in the returned [CapturedThemes] object. If the themes (or their
  /// theme data) change in the original subtree, those changes will not be
  /// applied to the themes captured in the [CapturedThemes] object - unless
  /// this method is called again to re-capture the updated themes.
  ///
  /// To wrap a [Widget] in the captured themes, call [CapturedThemes.wrap].
  ///
  /// This method can be expensive if there are many widgets between `from` and
  /// `to` (it walks the element tree between those nodes).
  static CapturedThemes capture({ required BuildContext from, required BuildContext? to }) {
    assert(from != null);

    if (from == to) {
      // Nothing to capture.
      return CapturedThemes._(const <InheritedTheme>[]);
    }

    final List<InheritedTheme> themes = <InheritedTheme>[];
    final Set<Type> themeTypes = <Type>{};
    late bool debugDidFindAncestor;
    assert(() {
      debugDidFindAncestor = to == null;
      return true;
    }());
    from.visitAncestorElements((Element ancestor) {
      if (ancestor == to) {
        assert(() {
          debugDidFindAncestor = true;
          return true;
        }());
        return false;
      }
      if (ancestor is InheritedElement && ancestor.widget is InheritedTheme) {
        final InheritedTheme theme = ancestor.widget as InheritedTheme;
        final Type themeType = theme.runtimeType;
        // Only remember the first theme of any type. This assumes
        // that inherited themes completely shadow ancestors of the
        // same type.
        if (!themeTypes.contains(themeType)) {
          themeTypes.add(themeType);
          themes.add(theme);
        }
      }
      return true;
    });

    assert(debugDidFindAncestor, 'The provided `to` context must be an ancestor of the `from` context.');
    return CapturedThemes._(themes);
  }
}

/// Stores a list of captured [InheritedTheme]s that can be wrapped around a
/// child [Widget].
///
/// Used as return type by [InheritedTheme.capture].
class CapturedThemes {
  CapturedThemes._(this._themes);

  final List<InheritedTheme> _themes;

  /// Wraps a `child` [Widget] in the [InheritedTheme]s captured in this object.
  Widget wrap(Widget child) {
    return _CaptureAll(themes: _themes, child: child);
  }
}

class _CaptureAll extends StatelessWidget {
  const _CaptureAll({
    required this.themes,
    required this.child,
  }) : assert(themes != null), assert(child != null);

  final List<InheritedTheme> themes;
  final Widget child;

  @override
  Widget build(BuildContext context) {
    Widget wrappedChild = child;
    for (final InheritedTheme theme in themes) {
      wrappedChild = theme.wrap(context, wrappedChild);
    }
    return wrappedChild;
  }
}
