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

/// 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] to construct a widget
/// that will wrap a child in all of the inherited themes which
/// are present in a build context but are not present in the
/// context that the returned widget is eventually built in.
///
/// 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 depend on inherited widget ancestors of the context
/// it's built in.
///
/// {@tool dartpad --template=freeform}
/// This example demonstrates how `InheritedTheme.captureAll()` can be used
/// to wrap the contents of a new route with the inherited themes that
/// are present when the route is built - but are not present when route
/// is actually shown.
///
/// If the same code is run without `InheritedTheme.captureAll(), 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.
///
/// ```dart imports
/// import 'package:flutter/material.dart';
/// ```
///
/// ```dart main
/// void main() {
///   runApp(MyApp());
/// }
/// ```
///
/// ```dart
/// class MyAppBody extends StatelessWidget {
///   @override
///   Widget build(BuildContext context) {
///     return GestureDetector(
///       onTap: () {
///         Navigator.of(context).push(
///           MaterialPageRoute(
///             builder: (BuildContext _) {
///               // InheritedTheme.captureAll() saves references to themes that
///               // are found above the context provided to this widget's build
///               // method, notably the DefaultTextStyle defined in MyApp. The
///               // context passed to the MaterialPageRoute's builder is not used,
///               // because its ancestors are above MyApp's home.
///               return InheritedTheme.captureAll(context, Container(
///                 alignment: Alignment.center,
///                 color: Theme.of(context).colorScheme.surface,
///                 child: Text('Hello World'),
///               ));
///             },
///           ),
///         );
///       },
///       child: Center(child: Text('Tap Here')),
///     );
///   }
/// }
///
/// class MyApp extends StatelessWidget {
///   @override
///   Widget build(BuildContext context) {
///     return MaterialApp(
///       home: Scaffold(
///         // Override the DefaultTextStyle defined by the Scaffold.
///         // Descendant widgets will inherit this big blue text style.
///         body: DefaultTextStyle(
///           style: TextStyle(fontSize: 48, color: Colors.blue),
///           child: MyAppBody(),
///         ),
///       ),
///     );
///   }
/// }
/// ```
/// {@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({
    Key? key,
    required Widget child,
  }) : super(key: key, child: child);

  /// Return a copy of this inherited theme with the specified [child].
  ///
  /// If the identical inherited theme is already visible from [context] then
  /// just return the [child].
  ///
  /// This implementation for [TooltipTheme] is typical:
  /// ```dart
  /// Widget wrap(BuildContext context, Widget child) {
  ///   final TooltipTheme ancestorTheme = context.findAncestorWidgetOfExactType<TooltipTheme>());
  ///   return identical(this, ancestorTheme) ? child : 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 visible from [context].
  static Widget captureAll(BuildContext context, Widget child) {
    assert(child != null);
    assert(context != null);

    final List<InheritedTheme> themes = <InheritedTheme>[];
    final Set<Type> themeTypes = <Type>{};
    context.visitAncestorElements((Element ancestor) {
      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;
    });

    return _CaptureAll(themes: themes, child: child);
  }
}

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

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