// 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.

// TODO(yjbanov): optimization opportunities (see also houdini_painter.js)
// - collapse non-drawing paint operations
// - avoid producing DOM-based clips if there is no text
// - evaluate using stylesheets for static CSS properties
// - evaluate reusing houdini canvases
// @dart = 2.6
part of engine;

/// A canvas that renders to a combination of HTML DOM and CSS Custom Paint API.
///
/// This canvas produces paint commands for houdini_painter.js to apply. This
/// class must be kept in sync with houdini_painter.js.
class HoudiniCanvas extends EngineCanvas with SaveElementStackTracking {
  @override
  final html.Element rootElement = html.Element.tag('flt-houdini');

  /// The rectangle positioned relative to the parent layer's coordinate system
  /// where this canvas paints.
  ///
  /// Painting outside the bounds of this rectangle is cropped.
  final ui.Rect bounds;

  HoudiniCanvas(this.bounds) {
    // TODO(yjbanov): would it be faster to specify static values in a
    //                stylesheet and let the browser apply them?
    rootElement.style
      ..position = 'absolute'
      ..top = '0'
      ..left = '0'
      ..width = '${bounds.size.width}px'
      ..height = '${bounds.size.height}px'
      ..backgroundImage = 'paint(flt)';
  }

  /// Prepare to reuse this canvas by clearing it's current contents.
  @override
  void clear() {
    super.clear();
    _serializedCommands = <List<dynamic>>[];
    // TODO(yjbanov): we should measure if reusing old elements is beneficial.
    domRenderer.clearDom(rootElement);
  }

  /// Paint commands serialized for sending to the CSS custom painter.
  List<List<dynamic>> _serializedCommands = <List<dynamic>>[];

  void apply(PaintCommand command) {
    // Some commands are applied purely in HTML DOM and do not need to be
    // serialized.
    if (command is! PaintDrawParagraph &&
        command is! PaintDrawImageRect &&
        command is! PaintTransform) {
      command.serializeToCssPaint(_serializedCommands);
    }
    command.apply(this);
  }

  /// Sends the paint commands to the CSS custom painter for painting.
  void commit() {
    if (_serializedCommands.isNotEmpty) {
      rootElement.style.setProperty('--flt', json.encode(_serializedCommands));
    } else {
      rootElement.style.removeProperty('--flt');
    }
  }

  @override
  void clipRect(ui.Rect rect) {
    final html.Element clip = html.Element.tag('flt-clip-rect');
    final String cssTransform = matrix4ToCssTransform(
        transformWithOffset(currentTransform, ui.Offset(rect.left, rect.top)));
    clip.style
      ..overflow = 'hidden'
      ..position = 'absolute'
      ..transform = cssTransform
      ..width = '${rect.width}px'
      ..height = '${rect.height}px';

    // The clipping element will translate the coordinate system as well, which
    // is not what a clip should do. To offset that we translate in the opposite
    // direction.
    super.translate(-rect.left, -rect.top);

    currentElement.append(clip);
    pushElement(clip);
  }

  @override
  void clipRRect(ui.RRect rrect) {
    final ui.Rect outer = rrect.outerRect;
    if (rrect.isRect) {
      clipRect(outer);
      return;
    }

    final html.Element clip = html.Element.tag('flt-clip-rrect');
    final html.CssStyleDeclaration style = clip.style;
    style
      ..overflow = 'hidden'
      ..position = 'absolute'
      ..transform = 'translate(${outer.left}px, ${outer.right}px)'
      ..width = '${outer.width}px'
      ..height = '${outer.height}px';

    if (rrect.tlRadiusY == rrect.tlRadiusX) {
      style.borderTopLeftRadius = '${rrect.tlRadiusX}px';
    } else {
      style.borderTopLeftRadius = '${rrect.tlRadiusX}px ${rrect.tlRadiusY}px';
    }

    if (rrect.trRadiusY == rrect.trRadiusX) {
      style.borderTopRightRadius = '${rrect.trRadiusX}px';
    } else {
      style.borderTopRightRadius = '${rrect.trRadiusX}px ${rrect.trRadiusY}px';
    }

    if (rrect.brRadiusY == rrect.brRadiusX) {
      style.borderBottomRightRadius = '${rrect.brRadiusX}px';
    } else {
      style.borderBottomRightRadius =
          '${rrect.brRadiusX}px ${rrect.brRadiusY}px';
    }

    if (rrect.blRadiusY == rrect.blRadiusX) {
      style.borderBottomLeftRadius = '${rrect.blRadiusX}px';
    } else {
      style.borderBottomLeftRadius =
          '${rrect.blRadiusX}px ${rrect.blRadiusY}px';
    }

    // The clipping element will translate the coordinate system as well, which
    // is not what a clip should do. To offset that we translate in the opposite
    // direction.
    super.translate(-rrect.left, -rrect.top);

    currentElement.append(clip);
    pushElement(clip);
  }

  @override
  void clipPath(ui.Path path) {
    // TODO(yjbanov): implement.
  }

  @override
  void drawColor(ui.Color color, ui.BlendMode blendMode) {
    // Drawn using CSS Paint.
  }

  @override
  void drawLine(ui.Offset p1, ui.Offset p2, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawPaint(SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawRect(ui.Rect rect, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawRRect(ui.RRect rrect, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawDRRect(ui.RRect outer, ui.RRect inner, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawOval(ui.Rect rect, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawCircle(ui.Offset c, double radius, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawPath(ui.Path path, SurfacePaintData paint) {
    // Drawn using CSS Paint.
  }

  @override
  void drawShadow(ui.Path path, ui.Color color, double elevation,
      bool transparentOccluder) {
    // Drawn using CSS Paint.
  }

  @override
  void drawImage(ui.Image image, ui.Offset p, SurfacePaintData paint) {
    // TODO(yjbanov): implement.
  }

  @override
  void drawImageRect(
      ui.Image image, ui.Rect src, ui.Rect dst, SurfacePaintData paint) {
    // TODO(yjbanov): implement src rectangle
    final HtmlImage htmlImage = image;
    final html.Element imageBox = html.Element.tag('flt-img');
    final String cssTransform = matrix4ToCssTransform(
        transformWithOffset(currentTransform, ui.Offset(dst.left, dst.top)));
    imageBox.style
      ..position = 'absolute'
      ..transformOrigin = '0 0 0'
      ..width = '${dst.width.toInt()}px'
      ..height = '${dst.height.toInt()}px'
      ..transform = cssTransform
      ..backgroundImage = 'url(${htmlImage.imgElement.src})'
      ..backgroundRepeat = 'norepeat'
      ..backgroundSize = '${dst.width}px ${dst.height}px';
    currentElement.append(imageBox);
  }

  @override
  void drawParagraph(ui.Paragraph paragraph, ui.Offset offset) {
    final html.Element paragraphElement =
        _drawParagraphElement(paragraph, offset, transform: currentTransform);
    currentElement.append(paragraphElement);
  }

  @override
  void drawVertices(
      ui.Vertices vertices, ui.BlendMode blendMode, SurfacePaintData paint) {
    // TODO(flutter_web): implement.
  }

  @override
  void drawPoints(ui.PointMode pointMode, Float32List points, SurfacePaintData paint) {
    // TODO(flutter_web): implement.
  }

  @override
  void endOfPaint() {}
}

class _SaveElementStackEntry {
  _SaveElementStackEntry({
    @required this.savedElement,
    @required this.transform,
  });

  final html.Element savedElement;
  final Matrix4 transform;
}

/// Provides save stack tracking functionality to implementations of
/// [EngineCanvas].
mixin SaveElementStackTracking on EngineCanvas {
  static final Vector3 _unitZ = Vector3(0.0, 0.0, 1.0);

  final List<_SaveElementStackEntry> _saveStack = <_SaveElementStackEntry>[];

  /// The element at the top of the element stack, or [rootElement] if the stack
  /// is empty.
  html.Element get currentElement =>
      _elementStack.isEmpty ? rootElement : _elementStack.last;

  /// The stack that maintains the DOM elements used to express certain paint
  /// operations, such as clips.
  final List<html.Element> _elementStack = <html.Element>[];

  /// Pushes the [element] onto the element stack for the purposes of applying
  /// a paint effect using a DOM element, e.g. for clipping.
  ///
  /// The [restore] method automatically pops the element off the stack.
  void pushElement(html.Element element) {
    _elementStack.add(element);
  }

  /// Empties the save stack and the element stack, and resets the transform
  /// and clip parameters.
  ///
  /// Classes that override this method must call `super.clear()`.
  @override
  void clear() {
    _saveStack.clear();
    _elementStack.clear();
    _currentTransform = Matrix4.identity();
  }

  /// The current transformation matrix.
  Matrix4 get currentTransform => _currentTransform;
  Matrix4 _currentTransform = Matrix4.identity();

  /// Saves current clip and transform on the save stack.
  ///
  /// Classes that override this method must call `super.save()`.
  @override
  void save() {
    _saveStack.add(_SaveElementStackEntry(
      savedElement: currentElement,
      transform: _currentTransform.clone(),
    ));
  }

  /// Restores current clip and transform from the save stack.
  ///
  /// Classes that override this method must call `super.restore()`.
  @override
  void restore() {
    if (_saveStack.isEmpty) {
      return;
    }
    final _SaveElementStackEntry entry = _saveStack.removeLast();
    _currentTransform = entry.transform;

    // Pop out of any clips.
    while (currentElement != entry.savedElement) {
      _elementStack.removeLast();
    }
  }

  /// Multiplies the [currentTransform] matrix by a translation.
  ///
  /// Classes that override this method must call `super.translate()`.
  @override
  void translate(double dx, double dy) {
    _currentTransform.translate(dx, dy);
  }

  /// Scales the [currentTransform] matrix.
  ///
  /// Classes that override this method must call `super.scale()`.
  @override
  void scale(double sx, double sy) {
    _currentTransform.scale(sx, sy);
  }

  /// Rotates the [currentTransform] matrix.
  ///
  /// Classes that override this method must call `super.rotate()`.
  @override
  void rotate(double radians) {
    _currentTransform.rotate(_unitZ, radians);
  }

  /// Skews the [currentTransform] matrix.
  ///
  /// Classes that override this method must call `super.skew()`.
  @override
  void skew(double sx, double sy) {
    // DO NOT USE Matrix4.skew(sx, sy)! It treats sx and sy values as radians,
    // but in our case they are transform matrix values.
    final Matrix4 skewMatrix = Matrix4.identity();
    final Float32List storage = skewMatrix.storage;
    storage[1] = sy;
    storage[4] = sx;
    _currentTransform.multiply(skewMatrix);
  }

  /// Multiplies the [currentTransform] matrix by another matrix.
  ///
  /// Classes that override this method must call `super.transform()`.
  @override
  void transform(Float32List matrix4) {
    _currentTransform.multiply(Matrix4.fromFloat32List(matrix4));
  }
}
