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

// @dart = 2.6
part of engine;

/// Mixin used by surfaces that clip their contents using an overflowing DOM
/// element.
mixin _DomClip on PersistedContainerSurface {
  /// The dedicated child container element that's separate from the
  /// [rootElement] is used to compensate for the coordinate system shift
  /// introduced by the [rootElement] translation.
  @override
  html.Element get childContainer => _childContainer;
  html.Element _childContainer;

  @override
  void adoptElements(_DomClip oldSurface) {
    super.adoptElements(oldSurface);
    _childContainer = oldSurface._childContainer;
    oldSurface._childContainer = null;
  }

  @override
  html.Element createElement() {
    final html.Element element = defaultCreateElement('flt-clip');
    if (!debugShowClipLayers) {
      // Hide overflow in production mode. When debugging we want to see the
      // clipped picture in full.
      element.style
        ..overflow = 'hidden'
        ..zIndex = '0';
    } else {
      // Display the outline of the clipping region. When debugShowClipLayers is
      // `true` we don't hide clip overflow (see above). This outline helps
      // visualizing clip areas.
      element.style.boxShadow = 'inset 0 0 10px green';
    }
    _childContainer = html.Element.tag('flt-clip-interior');
    if (_debugExplainSurfaceStats) {
      // This creates an additional interior element. Count it too.
      _surfaceStatsFor(this).allocatedDomNodeCount++;
    }
    _childContainer.style.position = 'absolute';

    element.append(_childContainer);
    return element;
  }

  @override
  void discard() {
    super.discard();

    // Do not detach the child container from the root. It is permanently
    // attached. The elements are reused together and are detached from the DOM
    // together.
    _childContainer = null;
  }
}

/// A surface that creates a rectangular clip.
class PersistedClipRect extends PersistedContainerSurface
    with _DomClip
    implements ui.ClipRectEngineLayer {
  PersistedClipRect(PersistedClipRect oldLayer, this.rect) : super(oldLayer);

  final ui.Rect rect;

  @override
  void recomputeTransformAndClip() {
    _transform = parent._transform;
    _localClipBounds = rect;
    _localTransformInverse = null;
    _projectedClip = null;
  }

  @override
  html.Element createElement() {
    return super.createElement()..setAttribute('clip-type', 'rect');
  }

  @override
  void apply() {
    rootElement.style
      ..left = '${rect.left}px'
      ..top = '${rect.top}px'
      ..width = '${rect.right - rect.left}px'
      ..height = '${rect.bottom - rect.top}px';

    // Translate the child container in the opposite direction to compensate for
    // the shift in the coordinate system introduced by the translation of the
    // rootElement. Clipping in Flutter has no effect on the coordinate system.
    childContainer.style
      ..left = '${-rect.left}px'
      ..top = '${-rect.top}px';
  }

  @override
  void update(PersistedClipRect oldSurface) {
    super.update(oldSurface);
    if (rect != oldSurface.rect) {
      apply();
    }
  }

  @override
  bool get isClipping => true;
}

/// A surface that creates a rounded rectangular clip.
class PersistedClipRRect extends PersistedContainerSurface
    with _DomClip
    implements ui.ClipRRectEngineLayer {
  PersistedClipRRect(ui.EngineLayer oldLayer, this.rrect, this.clipBehavior)
      : super(oldLayer);

  final ui.RRect rrect;
  // TODO(yjbanov): can this be controlled in the browser?
  final ui.Clip clipBehavior;

  @override
  void recomputeTransformAndClip() {
    _transform = parent._transform;
    _localClipBounds = rrect.outerRect;
    _localTransformInverse = null;
    _projectedClip = null;
  }

  @override
  html.Element createElement() {
    return super.createElement()..setAttribute('clip-type', 'rrect');
  }

  @override
  void apply() {
    rootElement.style
      ..left = '${rrect.left}px'
      ..top = '${rrect.top}px'
      ..width = '${rrect.width}px'
      ..height = '${rrect.height}px'
      ..borderTopLeftRadius = '${rrect.tlRadiusX}px'
      ..borderTopRightRadius = '${rrect.trRadiusX}px'
      ..borderBottomRightRadius = '${rrect.brRadiusX}px'
      ..borderBottomLeftRadius = '${rrect.blRadiusX}px';

    // Translate the child container in the opposite direction to compensate for
    // the shift in the coordinate system introduced by the translation of the
    // rootElement. Clipping in Flutter has no effect on the coordinate system.
    childContainer.style
      ..left = '${-rrect.left}px'
      ..top = '${-rrect.top}px';
  }

  @override
  void update(PersistedClipRRect oldSurface) {
    super.update(oldSurface);
    if (rrect != oldSurface.rrect) {
      apply();
    }
  }

  @override
  bool get isClipping => true;
}

class PersistedPhysicalShape extends PersistedContainerSurface
    with _DomClip
    implements ui.PhysicalShapeEngineLayer {
  PersistedPhysicalShape(PersistedPhysicalShape oldLayer, this.path,
      this.elevation, int color, int shadowColor, this.clipBehavior)
      : color = ui.Color(color),
        shadowColor = ui.Color(shadowColor),
        pathBounds = path.getBounds(),
        super(oldLayer);

  final SurfacePath path;
  final ui.Rect pathBounds;
  final double elevation;
  final ui.Color color;
  final ui.Color shadowColor;
  final ui.Clip clipBehavior;
  html.Element _clipElement;

  @override
  void recomputeTransformAndClip() {
    _transform = parent._transform;

    final ui.RRect roundRect = path.webOnlyPathAsRoundedRect;
    if (roundRect != null) {
      _localClipBounds = roundRect.outerRect;
    } else {
      final ui.Rect rect = path.webOnlyPathAsRect;
      if (rect != null) {
        _localClipBounds = rect;
      } else {
        _localClipBounds = null;
      }
    }
    _localTransformInverse = null;
    _projectedClip = null;
  }

  void _applyColor() {
    rootElement.style.backgroundColor = colorToCssString(color);
  }

  void _applyShadow() {
    applyCssShadow(rootElement, pathBounds, elevation, shadowColor);
  }

  @override
  html.Element createElement() {
    return super.createElement()..setAttribute('clip-type', 'physical-shape');
  }

  @override
  void apply() {
    _applyColor();
    _applyShadow();
    _applyShape();
  }

  void _applyShape() {
    if (path == null) {
      return;
    }
    // Handle special case of round rect physical shape mapping to
    // rounded div.
    final ui.RRect roundRect = path.webOnlyPathAsRoundedRect;
    if (roundRect != null) {
      final String borderRadius =
          '${roundRect.tlRadiusX}px ${roundRect.trRadiusX}px '
          '${roundRect.brRadiusX}px ${roundRect.blRadiusX}px';
      final html.CssStyleDeclaration style = rootElement.style;
      style
        ..left = '${roundRect.left}px'
        ..top = '${roundRect.top}px'
        ..width = '${roundRect.width}px'
        ..height = '${roundRect.height}px'
        ..borderRadius = borderRadius;
      childContainer.style
        ..left = '${-roundRect.left}px'
        ..top = '${-roundRect.top}px';
      if (clipBehavior != ui.Clip.none) {
        style.overflow = 'hidden';
      }
      return;
    } else {
      final ui.Rect rect = path.webOnlyPathAsRect;
      if (rect != null) {
        final html.CssStyleDeclaration style = rootElement.style;
        style
          ..left = '${rect.left}px'
          ..top = '${rect.top}px'
          ..width = '${rect.width}px'
          ..height = '${rect.height}px'
          ..borderRadius = '';
        childContainer.style
          ..left = '${-rect.left}px'
          ..top = '${-rect.top}px';
        if (clipBehavior != ui.Clip.none) {
          style.overflow = 'hidden';
        }
        return;
      } else {
        final Ellipse ellipse = path.webOnlyPathAsCircle;
        if (ellipse != null) {
          final double rx = ellipse.radiusX;
          final double ry = ellipse.radiusY;
          final String borderRadius =
              rx == ry ? '${rx}px ' : '${rx}px ${ry}px ';
          final html.CssStyleDeclaration style = rootElement.style;
          final double left = ellipse.x - rx;
          final double top = ellipse.y - ry;
          style
            ..left = '${left}px'
            ..top = '${top}px'
            ..width = '${rx * 2}px'
            ..height = '${ry * 2}px'
            ..borderRadius = borderRadius;
          childContainer.style
            ..left = '${-left}px'
            ..top = '${-top}px';
          if (clipBehavior != ui.Clip.none) {
            style.overflow = 'hidden';
          }
          return;
        }
      }
    }

    final String svgClipPath = _pathToSvgClipPath(path,
        offsetX: -pathBounds.left,
        offsetY: -pathBounds.top,
        scaleX: 1.0 / pathBounds.width,
        scaleY: 1.0 / pathBounds.height);
    assert(_clipElement == null);
    _clipElement =
        html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer());
    domRenderer.append(rootElement, _clipElement);
    domRenderer.setElementStyle(
        rootElement, 'clip-path', 'url(#svgClip$_clipIdCounter)');
    domRenderer.setElementStyle(
        rootElement, '-webkit-clip-path', 'url(#svgClip$_clipIdCounter)');
    final html.CssStyleDeclaration rootElementStyle = rootElement.style;
    rootElementStyle
      ..overflow = ''
      ..left = '${pathBounds.left}px'
      ..top = '${pathBounds.top}px'
      ..width = '${pathBounds.width}px'
      ..height = '${pathBounds.height}px'
      ..borderRadius = '';
    childContainer.style
      ..left = '-${pathBounds.left}px'
      ..top = '-${pathBounds.top}px';
  }

  @override
  void update(PersistedPhysicalShape oldSurface) {
    super.update(oldSurface);
    if (oldSurface.color != color) {
      _applyColor();
    }
    if (oldSurface.elevation != elevation ||
        oldSurface.shadowColor != shadowColor) {
      _applyShadow();
    }
    if (oldSurface.path != path) {
      oldSurface._clipElement?.remove();
      domRenderer.setElementStyle(rootElement, 'clip-path', '');
      domRenderer.setElementStyle(rootElement, '-webkit-clip-path', '');
      _applyShape();
      // This null check is in update since we don't want to unnecessarily
      // clear style in apply on first build.
      if (path == null) {
        // Reset style on prior element when path becomes null.
        final html.CssStyleDeclaration style = rootElement.style;
        style.left = '';
        style.top = '';
        style.borderRadius = '';
      }
    } else {
      _clipElement = oldSurface._clipElement;
    }
    oldSurface._clipElement = null;
  }
}

/// A surface that clips it's children.
class PersistedClipPath extends PersistedContainerSurface
    implements ui.ClipPathEngineLayer {
  PersistedClipPath(
      PersistedClipPath oldLayer, this.clipPath, this.clipBehavior)
      : super(oldLayer);

  final ui.Path clipPath;
  final ui.Clip clipBehavior;
  html.Element _clipElement;

  @override
  html.Element createElement() {
    return defaultCreateElement('flt-clippath');
  }

  @override
  void recomputeTransformAndClip() {
    super.recomputeTransformAndClip();
    _localClipBounds ??= clipPath.getBounds();
  }

  @override
  void apply() {
    if (clipPath == null) {
      if (_clipElement != null) {
        domRenderer.setElementStyle(childContainer, 'clip-path', '');
        domRenderer.setElementStyle(childContainer, '-webkit-clip-path', '');
        _clipElement.remove();
        _clipElement = null;
      }
      return;
    }
    _clipElement?.remove();
    final String svgClipPath = createSvgClipDef(childContainer, clipPath);
    _clipElement =
        html.Element.html(svgClipPath, treeSanitizer: _NullTreeSanitizer());
    domRenderer.append(childContainer, _clipElement);
  }

  @override
  void update(PersistedClipPath oldSurface) {
    super.update(oldSurface);
    if (oldSurface.clipPath != clipPath) {
      _localClipBounds = null;
      oldSurface._clipElement?.remove();
      apply();
    } else {
      _clipElement = oldSurface._clipElement;
    }
    oldSurface._clipElement = null;
  }

  @override
  void discard() {
    _clipElement?.remove();
    _clipElement = null;
    super.discard();
  }

  @override
  bool get isClipping => true;
}

/// Creates an svg clipPath and applies it to [element].
String createSvgClipDef(html.HtmlElement element, ui.Path clipPath) {
  final ui.Rect pathBounds = clipPath.getBounds();
  final String svgClipPath = _pathToSvgClipPath(clipPath,
      scaleX: 1.0 / pathBounds.right, scaleY: 1.0 / pathBounds.bottom);
  domRenderer.setElementStyle(
      element, 'clip-path', 'url(#svgClip$_clipIdCounter)');
  domRenderer.setElementStyle(
      element, '-webkit-clip-path', 'url(#svgClip$_clipIdCounter)');
  // We need to set width and height for the clipElement to cover the
  // bounds of the path since browsers such as Safari and Edge
  // seem to incorrectly intersect the element bounding rect with
  // the clip path. Chrome and Firefox don't perform intersect instead they
  // use the path itself as source of truth.
  element.style
    ..width = '${pathBounds.right}px'
    ..height = '${pathBounds.bottom}px';
  return svgClipPath;
}
