// Copyright 2013 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:ui/ui.dart' as ui;

import '../color_filter.dart';
import '../vector_math.dart';
import 'canvas.dart';
import 'canvaskit_api.dart';
import 'color_filter.dart';
import 'embedded_views.dart';
import 'image_filter.dart';
import 'n_way_canvas.dart';
import 'painting.dart';
import 'path.dart';
import 'picture.dart';
import 'raster_cache.dart';

/// A layer to be composed into a scene.
///
/// A layer is the lowest-level rendering primitive. It represents an atomic
/// painting command.
abstract class Layer implements ui.EngineLayer {
  /// The layer that contains us as a child.
  ContainerLayer? parent;

  /// An estimated rectangle that this layer will draw into.
  ui.Rect paintBounds = ui.Rect.zero;

  /// Whether or not this layer actually needs to be painted in the scene.
  bool get needsPainting => !paintBounds.isEmpty;

  /// Pre-process this layer before painting.
  ///
  /// In this step, we compute the estimated [paintBounds] as well as
  /// apply heuristics to prepare the render cache for pictures that
  /// should be cached.
  void preroll(PrerollContext prerollContext, Matrix4 matrix);

  /// Paint this layer into the scene.
  void paint(PaintContext paintContext);

  // TODO(dnfield): Implement ui.EngineLayer.dispose for CanvasKit.
  // https://github.com/flutter/flutter/issues/82878
  @override
  void dispose() {}
}

/// A context shared by all layers during the preroll pass.
class PrerollContext {
  PrerollContext(this.rasterCache, this.viewEmbedder);

  /// A raster cache. Used to register candidates for caching.
  final RasterCache? rasterCache;

  /// A compositor for embedded HTML views.
  final HtmlViewEmbedder? viewEmbedder;

  final MutatorsStack mutatorsStack = MutatorsStack();

  ui.Rect get cullRect {
    ui.Rect cullRect = ui.Rect.largest;
    for (final Mutator m in mutatorsStack) {
      ui.Rect clipRect;
      switch (m.type) {
        case MutatorType.clipRect:
          clipRect = m.rect!;
        case MutatorType.clipRRect:
          clipRect = m.rrect!.outerRect;
        case MutatorType.clipPath:
          clipRect = m.path!.getBounds();
        default:
          continue;
      }
      cullRect = cullRect.intersect(clipRect);
    }
    return cullRect;
  }
}

/// A context shared by all layers during the paint pass.
class PaintContext {
  PaintContext(
    this.internalNodesCanvas,
    this.leafNodesCanvas,
    this.rasterCache,
    this.viewEmbedder,
  );

  /// A multi-canvas that applies clips, transforms, and opacity
  /// operations to all canvases (root canvas and overlay canvases for the
  /// platform views).
  CkNWayCanvas internalNodesCanvas;

  /// The canvas for leaf nodes to paint to.
  CkCanvas? leafNodesCanvas;

  /// A raster cache potentially containing pre-rendered pictures.
  final RasterCache? rasterCache;

  /// A compositor for embedded HTML views.
  final HtmlViewEmbedder? viewEmbedder;
}

/// A layer that contains child layers.
abstract class ContainerLayer extends Layer {
  final List<Layer> _layers = <Layer>[];

  /// The list of child layers.
  ///
  /// Useful in tests.
  List<Layer> get debugLayers => _layers;

  /// Register [child] as a child of this layer.
  void add(Layer child) {
    child.parent = this;
    _layers.add(child);
  }

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    paintBounds = prerollChildren(prerollContext, matrix);
  }

  /// Run [preroll] on all of the child layers.
  ///
  /// Returns a [Rect] that covers the paint bounds of all of the child layers.
  /// If all of the child layers have empty paint bounds, then the returned
  /// [Rect] is empty.
  ui.Rect prerollChildren(PrerollContext context, Matrix4 childMatrix) {
    ui.Rect childPaintBounds = ui.Rect.zero;
    for (final Layer layer in _layers) {
      layer.preroll(context, childMatrix);
      if (childPaintBounds.isEmpty) {
        childPaintBounds = layer.paintBounds;
      } else if (!layer.paintBounds.isEmpty) {
        childPaintBounds = childPaintBounds.expandToInclude(layer.paintBounds);
      }
    }
    return childPaintBounds;
  }

  /// Calls [paint] on all child layers that need painting.
  void paintChildren(PaintContext context) {
    assert(needsPainting);

    for (final Layer layer in _layers) {
      if (layer.needsPainting) {
        layer.paint(context);
      }
    }
  }
}

/// The top-most layer in the layer tree.
///
/// This layer does not draw anything. It's only used so we can add leaf layers
/// to [LayerSceneBuilder] without requiring a [ContainerLayer].
class RootLayer extends ContainerLayer {
  @override
  void paint(PaintContext paintContext) {
    paintChildren(paintContext);
  }
}

class BackdropFilterEngineLayer extends ContainerLayer
    implements ui.BackdropFilterEngineLayer {
  BackdropFilterEngineLayer(this._filter, this._blendMode);

  final ui.ImageFilter _filter;
  final ui.BlendMode _blendMode;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    final ui.Rect childBounds = prerollChildren(prerollContext, matrix);
    paintBounds = childBounds.expandToInclude(prerollContext.cullRect);
  }

  @override
  void paint(PaintContext paintContext) {
    final CkPaint paint = CkPaint()..blendMode = _blendMode;

    // Only apply the backdrop filter to the current canvas. If we apply the
    // backdrop filter to every canvas (i.e. by applying it to the
    // [internalNodesCanvas]), then later when we compose the canvases into a
    // single canvas, the backdrop filter will be applied multiple times.
    final CkCanvas currentCanvas = paintContext.leafNodesCanvas!;
    currentCanvas.saveLayerWithFilter(paintBounds, _filter, paint);
    paint.dispose();
    paintChildren(paintContext);
    currentCanvas.restore();
  }

  // TODO(dnfield): dispose of the _filter
  // https://github.com/flutter/flutter/issues/82832
}

/// A layer that clips its child layers by a given [Path].
class ClipPathEngineLayer extends ContainerLayer
    implements ui.ClipPathEngineLayer {
  ClipPathEngineLayer(this._clipPath, this._clipBehavior)
      : assert(_clipBehavior != ui.Clip.none);

  /// The path used to clip child layers.
  final CkPath _clipPath;
  final ui.Clip _clipBehavior;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    prerollContext.mutatorsStack.pushClipPath(_clipPath);
    final ui.Rect childPaintBounds = prerollChildren(prerollContext, matrix);
    final ui.Rect clipBounds = _clipPath.getBounds();
    if (childPaintBounds.overlaps(clipBounds)) {
      paintBounds = childPaintBounds.intersect(clipBounds);
    }
    prerollContext.mutatorsStack.pop();
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas
        .clipPath(_clipPath, _clipBehavior != ui.Clip.hardEdge);

    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.saveLayer(paintBounds, null);
    }
    paintChildren(paintContext);
    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.restore();
    }
    paintContext.internalNodesCanvas.restore();
  }
}

/// A layer that clips its child layers by a given [Rect].
class ClipRectEngineLayer extends ContainerLayer
    implements ui.ClipRectEngineLayer {
  ClipRectEngineLayer(this._clipRect, this._clipBehavior)
      : assert(_clipBehavior != ui.Clip.none);

  /// The rectangle used to clip child layers.
  final ui.Rect _clipRect;
  final ui.Clip _clipBehavior;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    prerollContext.mutatorsStack.pushClipRect(_clipRect);
    final ui.Rect childPaintBounds = prerollChildren(prerollContext, matrix);
    if (childPaintBounds.overlaps(_clipRect)) {
      paintBounds = childPaintBounds.intersect(_clipRect);
    }
    prerollContext.mutatorsStack.pop();
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas.clipRect(
      _clipRect,
      ui.ClipOp.intersect,
      _clipBehavior != ui.Clip.hardEdge,
    );
    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.saveLayer(_clipRect, null);
    }
    paintChildren(paintContext);
    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.restore();
    }
    paintContext.internalNodesCanvas.restore();
  }
}

/// A layer that clips its child layers by a given [RRect].
class ClipRRectEngineLayer extends ContainerLayer
    implements ui.ClipRRectEngineLayer {
  ClipRRectEngineLayer(this._clipRRect, this._clipBehavior)
      : assert(_clipBehavior != ui.Clip.none);

  /// The rounded rectangle used to clip child layers.
  final ui.RRect _clipRRect;
  final ui.Clip? _clipBehavior;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    prerollContext.mutatorsStack.pushClipRRect(_clipRRect);
    final ui.Rect childPaintBounds = prerollChildren(prerollContext, matrix);
    if (childPaintBounds.overlaps(_clipRRect.outerRect)) {
      paintBounds = childPaintBounds.intersect(_clipRRect.outerRect);
    }
    prerollContext.mutatorsStack.pop();
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas
        .clipRRect(_clipRRect, _clipBehavior != ui.Clip.hardEdge);
    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.saveLayer(paintBounds, null);
    }
    paintChildren(paintContext);
    if (_clipBehavior == ui.Clip.antiAliasWithSaveLayer) {
      paintContext.internalNodesCanvas.restore();
    }
    paintContext.internalNodesCanvas.restore();
  }
}

/// A layer that paints its children with the given opacity.
class OpacityEngineLayer extends ContainerLayer
    implements ui.OpacityEngineLayer {
  OpacityEngineLayer(this._alpha, this._offset);

  final int _alpha;
  final ui.Offset _offset;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    final Matrix4 childMatrix = Matrix4.copy(matrix);
    childMatrix.translate(_offset.dx, _offset.dy);
    prerollContext.mutatorsStack
        .pushTransform(Matrix4.translationValues(_offset.dx, _offset.dy, 0.0));
    prerollContext.mutatorsStack.pushOpacity(_alpha);
    super.preroll(prerollContext, childMatrix);
    prerollContext.mutatorsStack.pop();
    prerollContext.mutatorsStack.pop();
    paintBounds = paintBounds.translate(_offset.dx, _offset.dy);
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    final CkPaint paint = CkPaint();
    paint.color = ui.Color.fromARGB(_alpha, 0, 0, 0);

    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas.translate(_offset.dx, _offset.dy);

    final ui.Rect saveLayerBounds = paintBounds.shift(-_offset);

    paintContext.internalNodesCanvas.saveLayer(saveLayerBounds, paint);
    paint.dispose();
    paintChildren(paintContext);
    // Restore twice: once for the translate and once for the saveLayer.
    paintContext.internalNodesCanvas.restore();
    paintContext.internalNodesCanvas.restore();
  }
}

/// A layer that transforms its child layers by the given transform matrix.
class TransformEngineLayer extends ContainerLayer
    implements ui.TransformEngineLayer {
  TransformEngineLayer(this._transform);

  /// The matrix with which to transform the child layers.
  final Matrix4 _transform;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    final Matrix4 childMatrix = matrix.multiplied(_transform);
    prerollContext.mutatorsStack.pushTransform(_transform);
    final ui.Rect childPaintBounds =
        prerollChildren(prerollContext, childMatrix);
    paintBounds = _transform.transformRect(childPaintBounds);
    prerollContext.mutatorsStack.pop();
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas.transform(_transform.storage);
    paintChildren(paintContext);
    paintContext.internalNodesCanvas.restore();
  }
}

/// Translates its children along x and y coordinates.
///
/// This is a thin wrapper over [TransformEngineLayer] just so the framework
/// gets the "OffsetEngineLayer" when calling `runtimeType.toString()`. This is
/// better for debugging.
class OffsetEngineLayer extends TransformEngineLayer
    implements ui.OffsetEngineLayer {
  OffsetEngineLayer(double dx, double dy)
      : super(Matrix4.translationValues(dx, dy, 0.0));
}

/// A layer that applies an [ui.ImageFilter] to its children.
class ImageFilterEngineLayer extends ContainerLayer
    implements ui.ImageFilterEngineLayer {
  ImageFilterEngineLayer(this._filter, this._offset);

  final ui.Offset _offset;
  final ui.ImageFilter _filter;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    final Matrix4 childMatrix = Matrix4.copy(matrix);
    childMatrix.translate(_offset.dx, _offset.dy);
    prerollContext.mutatorsStack
        .pushTransform(Matrix4.translationValues(_offset.dx, _offset.dy, 0.0));
    final CkManagedSkImageFilterConvertible convertible;
    if (_filter is ui.ColorFilter) {
      convertible = createCkColorFilter(_filter as EngineColorFilter)!;
    } else {
      convertible = _filter as CkManagedSkImageFilterConvertible;
    }
    final ui.Rect childPaintBounds =
        prerollChildren(prerollContext, childMatrix);
    convertible.imageFilter((SkImageFilter filter) {
      // If the filter is a ColorFilter, the extended paint bounds will be the
      // entire screen, which is not what we want.
      if (_filter is ui.ColorFilter) {
        paintBounds = childPaintBounds;
      } else {
        paintBounds =
            rectFromSkIRect(filter.getOutputBounds(toSkRect(childPaintBounds)));
      }
    });
    prerollContext.mutatorsStack.pop();
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);
    paintContext.internalNodesCanvas.save();
    paintContext.internalNodesCanvas.translate(_offset.dx, _offset.dy);
    paintContext.internalNodesCanvas
        .clipRect(paintBounds, ui.ClipOp.intersect, false);
    final CkPaint paint = CkPaint();
    paint.imageFilter = _filter;
    paintContext.internalNodesCanvas.saveLayer(paintBounds, paint);
    paint.dispose();
    paintChildren(paintContext);
    paintContext.internalNodesCanvas.restore();
    paintContext.internalNodesCanvas.restore();
  }

  // TODO(dnfield): dispose of the _filter
  // https://github.com/flutter/flutter/issues/82832
}

class ShaderMaskEngineLayer extends ContainerLayer
    implements ui.ShaderMaskEngineLayer {
  ShaderMaskEngineLayer(
      this.shader, this.maskRect, this.blendMode, this.filterQuality);

  final ui.Shader shader;
  final ui.Rect maskRect;
  final ui.BlendMode blendMode;
  final ui.FilterQuality filterQuality;

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.internalNodesCanvas.saveLayer(paintBounds, null);
    paintChildren(paintContext);

    final CkPaint paint = CkPaint();
    paint.shader = shader;
    paint.blendMode = blendMode;
    paint.filterQuality = filterQuality;

    paintContext.leafNodesCanvas!.save();
    paintContext.leafNodesCanvas!.translate(maskRect.left, maskRect.top);

    paintContext.leafNodesCanvas!.drawRect(
        ui.Rect.fromLTWH(0, 0, maskRect.width, maskRect.height), paint);
    paint.dispose();
    paintContext.leafNodesCanvas!.restore();

    paintContext.internalNodesCanvas.restore();
  }
}

/// A layer containing a [Picture].
class PictureLayer extends Layer {
  PictureLayer(this.picture, this.offset, this.isComplex, this.willChange);

  /// The picture to paint into the canvas.
  final CkPicture picture;

  /// The offset at which to paint the picture.
  final ui.Offset offset;

  /// A hint to the compositor about whether this picture is complex.
  final bool isComplex;

  /// A hint to the compositor that this picture is likely to change.
  final bool willChange;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    paintBounds = picture.cullRect.shift(offset);
  }

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    paintContext.leafNodesCanvas!.save();
    paintContext.leafNodesCanvas!.translate(offset.dx, offset.dy);

    paintContext.leafNodesCanvas!.drawPicture(picture);
    paintContext.leafNodesCanvas!.restore();
  }
}

/// A layer which contains a [ui.ColorFilter].
class ColorFilterEngineLayer extends ContainerLayer
    implements ui.ColorFilterEngineLayer {
  ColorFilterEngineLayer(this.filter);

  final ui.ColorFilter filter;

  @override
  void paint(PaintContext paintContext) {
    assert(needsPainting);

    final CkPaint paint = CkPaint();
    paint.colorFilter = filter;

    // We need to clip because if the ColorFilter affects transparent black,
    // then it will fill the entire `cullRect` of the picture, ignoring the
    // `paintBounds` passed to `saveLayer`. See:
    // https://github.com/flutter/flutter/issues/88866
    paintContext.internalNodesCanvas.save();

    // TODO(hterkelsen): Only clip if the ColorFilter affects transparent black.
    paintContext.internalNodesCanvas
        .clipRect(paintBounds, ui.ClipOp.intersect, false);

    paintContext.internalNodesCanvas.saveLayer(paintBounds, paint);
    paintChildren(paintContext);
    paintContext.internalNodesCanvas.restore();
    paintContext.internalNodesCanvas.restore();
    paint.dispose();
  }
}

/// A layer which renders a platform view (an HTML element in this case).
class PlatformViewLayer extends Layer {
  PlatformViewLayer(this.viewId, this.offset, this.width, this.height);

  final int viewId;
  final ui.Offset offset;
  final double width;
  final double height;

  @override
  void preroll(PrerollContext prerollContext, Matrix4 matrix) {
    paintBounds = ui.Rect.fromLTWH(offset.dx, offset.dy, width, height);

    /// ViewEmbedder is set to null when screenshotting. Therefore, skip
    /// rendering
    prerollContext.viewEmbedder?.prerollCompositeEmbeddedView(
      viewId,
      EmbeddedViewParams(
        offset,
        ui.Size(width, height),
        prerollContext.mutatorsStack,
      ),
    );
  }

  @override
  void paint(PaintContext paintContext) {
    final CkCanvas? canvas =
        paintContext.viewEmbedder?.compositeEmbeddedView(viewId);
    if (canvas != null) {
      paintContext.leafNodesCanvas = canvas;
    }
  }
}
