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

import 'debug.dart';
import 'material.dart';

/// A convenience widget for drawing images and other decorations on [Material]
/// widgets, so that [InkWell] and [InkResponse] splashes will render over them.
///
/// Ink splashes and highlights, as rendered by [InkWell] and [InkResponse],
/// draw on the actual underlying [Material], under whatever widgets are drawn
/// over the material (such as [Text] and [Icon]s). If an opaque image is drawn
/// over the [Material] (maybe using a [Container] or [DecoratedBox]), these ink
/// effects will not be visible, as they will be entirely obscured by the opaque
/// graphics drawn above the [Material].
///
/// This widget draws the given [Decoration] directly on the [Material], in the
/// same way that [InkWell] and [InkResponse] draw there. This allows the
/// splashes to be drawn above the otherwise opaque graphics.
///
/// An alternative solution is to use a [MaterialType.transparency] material
/// above the opaque graphics, so that the ink responses from [InkWell]s and
/// [InkResponse]s will be drawn on the transparent material on top of the
/// opaque graphics, rather than under the opaque graphics on the underlying
/// [Material].
///
/// ## Limitations
///
/// This widget is subject to the same limitations as other ink effects, as
/// described in the documentation for [Material]. Most notably, the position of
/// an [Ink] widget must not change during the lifetime of the [Material] object
/// unless a [LayoutChangedNotification] is dispatched each frame that the
/// position changes. This is done automatically for [ListView] and other
/// scrolling widgets, but is not done for animated transitions such as
/// [SlideTransition].
///
/// Additionally, if multiple [Ink] widgets paint on the same [Material] in the
/// same location, their relative order is not guaranteed. The decorations will
/// be painted in the order that they were added to the material, which
/// generally speaking will match the order they are given in the widget tree,
/// but this order may appear to be somewhat random in more dynamic situations.
///
/// {@tool snippet}
///
/// This example shows how a [Material] widget can have a yellow rectangle drawn
/// on it using [Ink], while still having ink effects over the yellow rectangle:
///
/// ```dart
/// Material(
///   color: Colors.teal[900],
///   child: Center(
///     child: Ink(
///       color: Colors.yellow,
///       width: 200.0,
///       height: 100.0,
///       child: InkWell(
///         onTap: () { /* ... */ },
///         child: const Center(
///           child: Text('YELLOW'),
///         )
///       ),
///     ),
///   ),
/// )
/// ```
/// {@end-tool}
/// {@tool snippet}
///
/// The following example shows how an image can be printed on a [Material]
/// widget with an [InkWell] above it:
///
/// ```dart
/// Material(
///   color: Colors.grey[800],
///   child: Center(
///     child: Ink.image(
///       image: const AssetImage('cat.jpeg'),
///       fit: BoxFit.cover,
///       width: 300.0,
///       height: 200.0,
///       child: InkWell(
///         onTap: () { /* ... */ },
///         child: const Align(
///           alignment: Alignment.topLeft,
///           child: Padding(
///             padding: EdgeInsets.all(10.0),
///             child: Text(
///               'KITTEN',
///               style: TextStyle(
///                 fontWeight: FontWeight.w900,
///                 color: Colors.white,
///               ),
///             ),
///           ),
///         )
///       ),
///     ),
///   ),
/// )
/// ```
/// {@end-tool}
///
/// See also:
///
///  * [Container], a more generic form of this widget which paints itself,
///    rather that deferring to the nearest [Material] widget.
///  * [InkDecoration], the [InkFeature] subclass used by this widget to paint
///    on [Material] widgets.
///  * [InkWell] and [InkResponse], which also draw on [Material] widgets.
class Ink extends StatefulWidget {
  /// Paints a decoration (which can be a simple color) on a [Material].
  ///
  /// The [height] and [width] values include the [padding].
  ///
  /// The `color` argument is a shorthand for
  /// `decoration: BoxDecoration(color: color)`, which means you cannot supply
  /// both a `color` and a `decoration` argument. If you want to have both a
  /// `color` and a `decoration`, you can pass the color as the `color`
  /// argument to the `BoxDecoration`.
  ///
  /// If there is no intention to render anything on this decoration, consider
  /// using a [Container] with a [BoxDecoration] instead.
  Ink({
    Key? key,
    this.padding,
    Color? color,
    Decoration? decoration,
    this.width,
    this.height,
    this.child,
  }) : assert(padding == null || padding.isNonNegative),
       assert(decoration == null || decoration.debugAssertIsValid()),
       assert(color == null || decoration == null,
         'Cannot provide both a color and a decoration\n'
         'The color argument is just a shorthand for "decoration: BoxDecoration(color: color)".',
       ),
       decoration = decoration ?? (color != null ? BoxDecoration(color: color) : null),
       super(key: key);

  /// Creates a widget that shows an image (obtained from an [ImageProvider]) on
  /// a [Material].
  ///
  /// This argument is a shorthand for passing a [BoxDecoration] that has only
  /// its [BoxDecoration.image] property set to the [Ink] constructor. The
  /// properties of the [DecorationImage] of that [BoxDecoration] are set
  /// according to the arguments passed to this method.
  ///
  /// The `image` argument must not be null. If there is no
  /// intention to render anything on this image, consider using a
  /// [Container] with a [BoxDecoration.image] instead. The `onImageError`
  /// argument may be provided to listen for errors when resolving the image.
  ///
  /// The `alignment`, `repeat`, and `matchTextDirection` arguments must not
  /// be null either, but they have default values.
  ///
  /// See [paintImage] for a description of the meaning of these arguments.
  Ink.image({
    Key? key,
    this.padding,
    required ImageProvider image,
    ImageErrorListener? onImageError,
    ColorFilter? colorFilter,
    BoxFit? fit,
    AlignmentGeometry alignment = Alignment.center,
    Rect? centerSlice,
    ImageRepeat repeat = ImageRepeat.noRepeat,
    bool matchTextDirection = false,
    this.width,
    this.height,
    this.child,
  }) : assert(padding == null || padding.isNonNegative),
       assert(image != null),
       assert(alignment != null),
       assert(repeat != null),
       assert(matchTextDirection != null),
       decoration = BoxDecoration(
         image: DecorationImage(
           image: image,
           onError: onImageError,
           colorFilter: colorFilter,
           fit: fit,
           alignment: alignment,
           centerSlice: centerSlice,
           repeat: repeat,
           matchTextDirection: matchTextDirection,
         ),
       ),
       super(key: key);

  /// The [child] contained by the container.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget? child;

  /// Empty space to inscribe inside the [decoration]. The [child], if any, is
  /// placed inside this padding.
  ///
  /// This padding is in addition to any padding inherent in the [decoration];
  /// see [Decoration.padding].
  final EdgeInsetsGeometry? padding;

  /// The decoration to paint on the nearest ancestor [Material] widget.
  ///
  /// A shorthand for specifying just a solid color is available in the
  /// constructor: set the `color` argument instead of the `decoration`
  /// argument.
  ///
  /// A shorthand for specifying just an image is also available using the
  /// [Ink.image] constructor.
  final Decoration? decoration;

  /// A width to apply to the [decoration] and the [child]. The width includes
  /// any [padding].
  final double? width;

  /// A height to apply to the [decoration] and the [child]. The height includes
  /// any [padding].
  final double? height;

  EdgeInsetsGeometry get _paddingIncludingDecoration {
    if (decoration == null || decoration!.padding == null)
      return padding ?? EdgeInsets.zero;
    final EdgeInsetsGeometry decorationPadding = decoration!.padding!;
    if (padding == null)
      return decorationPadding;
    return padding!.add(decorationPadding);
  }

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DiagnosticsProperty<EdgeInsetsGeometry>('padding', padding, defaultValue: null));
    properties.add(DiagnosticsProperty<Decoration>('bg', decoration, defaultValue: null));
  }

  @override
  State<Ink> createState() => _InkState();
}

class _InkState extends State<Ink> {
  final GlobalKey _boxKey = GlobalKey();
  InkDecoration? _ink;

  void _handleRemoved() {
    _ink = null;
  }

  @override
  void deactivate() {
    _ink?.dispose();
    assert(_ink == null);
    super.deactivate();
  }

  Widget _build(BuildContext context) {
    // By creating the InkDecoration from within a Builder widget, we can
    // use the RenderBox of the Padding widget.
    if (_ink == null) {
      _ink = InkDecoration(
        decoration: widget.decoration,
        configuration: createLocalImageConfiguration(context),
        controller: Material.of(context)!,
        referenceBox: _boxKey.currentContext!.findRenderObject()! as RenderBox,
        onRemoved: _handleRemoved,
      );
    } else {
      _ink!.decoration = widget.decoration;
      _ink!.configuration = createLocalImageConfiguration(context);
    }
    return widget.child ?? Container();
  }

  @override
  Widget build(BuildContext context) {
    assert(debugCheckHasMaterial(context));
    Widget result = Padding(
      key: _boxKey,
      padding: widget._paddingIncludingDecoration,
      child: Builder(builder: _build),
    );
    if (widget.width != null || widget.height != null) {
      result = SizedBox(
        width: widget.width,
        height: widget.height,
        child: result,
      );
    }
    return result;
  }
}

/// A decoration on a part of a [Material].
///
/// This object is rarely created directly. Instead of creating an ink
/// decoration directly, consider using an [Ink] widget, which uses this class
/// in combination with [Padding] and [ConstrainedBox] to draw a decoration on a
/// [Material].
///
/// See also:
///
///  * [Ink], the corresponding widget.
///  * [InkResponse], which uses gestures to trigger ink highlights and ink
///    splashes in the parent [Material].
///  * [InkWell], which is a rectangular [InkResponse] (the most common type of
///    ink response).
///  * [Material], which is the widget on which the ink is painted.
class InkDecoration extends InkFeature {
  /// Draws a decoration on a [Material].
  InkDecoration({
    required Decoration? decoration,
    required ImageConfiguration configuration,
    required MaterialInkController controller,
    required RenderBox referenceBox,
    VoidCallback? onRemoved,
  }) : assert(configuration != null),
       _configuration = configuration,
       super(controller: controller, referenceBox: referenceBox, onRemoved: onRemoved) {
    this.decoration = decoration;
    controller.addInkFeature(this);
  }

  BoxPainter? _painter;

  /// What to paint on the [Material].
  ///
  /// The decoration is painted at the position and size of the [referenceBox],
  /// on the [Material] that owns the [controller].
  Decoration? get decoration => _decoration;
  Decoration? _decoration;
  set decoration(Decoration? value) {
    if (value == _decoration)
      return;
    _decoration = value;
    _painter?.dispose();
    _painter = _decoration?.createBoxPainter(_handleChanged);
    controller.markNeedsPaint();
  }

  /// The configuration to pass to the [BoxPainter] obtained from the
  /// [decoration], when painting.
  ///
  /// The [ImageConfiguration.size] field is ignored (and replaced by the size
  /// of the [referenceBox], at paint time).
  ImageConfiguration get configuration => _configuration;
  ImageConfiguration _configuration;
  set configuration(ImageConfiguration value) {
    assert(value != null);
    if (value == _configuration)
      return;
    _configuration = value;
    controller.markNeedsPaint();
  }

  void _handleChanged() {
    controller.markNeedsPaint();
  }

  @override
  void dispose() {
    _painter?.dispose();
    super.dispose();
  }

  @override
  void paintFeature(Canvas canvas, Matrix4 transform) {
    if (_painter == null)
      return;
    final Offset? originOffset = MatrixUtils.getAsTranslation(transform);
    final ImageConfiguration sizedConfiguration = configuration.copyWith(
      size: referenceBox.size,
    );
    if (originOffset == null) {
      canvas.save();
      canvas.transform(transform.storage);
      _painter!.paint(canvas, Offset.zero, sizedConfiguration);
      canvas.restore();
    } else {
      _painter!.paint(canvas, originOffset, sizedConfiguration);
    }
  }
}
