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

/// Renders an RRect using path primitives.
abstract class _RRectRenderer {
  // TODO(mdebbar): Backport the overlapping corners fix to houdini_painter.js
  // To draw the rounded rectangle, perform the following steps:
  //   0. Ensure border radius don't overlap
  //   1. Flip left,right top,bottom since web doesn't support flipped
  //      coordinates with negative radii.
  //   2. draw the line for the top
  //   3. draw the arc for the top-right corner
  //   4. draw the line for the right side
  //   5. draw the arc for the bottom-right corner
  //   6. draw the line for the bottom of the rectangle
  //   7. draw the arc for the bottom-left corner
  //   8. draw the line for the left side
  //   9. draw the arc for the top-left corner
  //
  // After drawing, the current point will be the left side of the top of the
  // rounded rectangle (after the corner).
  // TODO(het): Confirm that this is the end point in Flutter for RRect

  void render(ui.RRect inputRRect,
      {bool startNewPath = true, bool reverse = false}) {
    // Ensure border radius curves never overlap
    final ui.RRect rrect = inputRRect.scaleRadii();

    double left = rrect.left;
    double right = rrect.right;
    double top = rrect.top;
    double bottom = rrect.bottom;
    if (left > right) {
      left = right;
      right = rrect.left;
    }
    if (top > bottom) {
      top = bottom;
      bottom = rrect.top;
    }
    final double trRadiusX = rrect.trRadiusX.abs();
    final double tlRadiusX = rrect.tlRadiusX.abs();
    final double trRadiusY = rrect.trRadiusY.abs();
    final double tlRadiusY = rrect.tlRadiusY.abs();
    final double blRadiusX = rrect.blRadiusX.abs();
    final double brRadiusX = rrect.brRadiusX.abs();
    final double blRadiusY = rrect.blRadiusY.abs();
    final double brRadiusY = rrect.brRadiusY.abs();

    if (!reverse) {
      if (startNewPath) {
        beginPath();
      }

      moveTo(left + trRadiusX, top);

      // Top side and top-right corner
      lineTo(right - trRadiusX, top);
      ellipse(
        right - trRadiusX,
        top + trRadiusY,
        trRadiusX,
        trRadiusY,
        0,
        1.5 * math.pi,
        2.0 * math.pi,
        false,
      );

      // Right side and bottom-right corner
      lineTo(right, bottom - brRadiusY);
      ellipse(
        right - brRadiusX,
        bottom - brRadiusY,
        brRadiusX,
        brRadiusY,
        0,
        0,
        0.5 * math.pi,
        false,
      );

      // Bottom side and bottom-left corner
      lineTo(left + blRadiusX, bottom);
      ellipse(
        left + blRadiusX,
        bottom - blRadiusY,
        blRadiusX,
        blRadiusY,
        0,
        0.5 * math.pi,
        math.pi,
        false,
      );

      // Left side and top-left corner
      lineTo(left, top + tlRadiusY);
      ellipse(
        left + tlRadiusX,
        top + tlRadiusY,
        tlRadiusX,
        tlRadiusY,
        0,
        math.pi,
        1.5 * math.pi,
        false,
      );
    } else {
      // Draw the rounded rectangle, counterclockwise.
      moveTo(right - trRadiusX, top);

      if (startNewPath) {
        beginPath();
      }

      // Top side and top-left corner
      lineTo(left + tlRadiusX, top);
      ellipse(
        left + tlRadiusX,
        top + tlRadiusY,
        tlRadiusX,
        tlRadiusY,
        0,
        1.5 * math.pi,
        1 * math.pi,
        true,
      );

      // Left side and bottom-left corner
      lineTo(left, bottom - blRadiusY);
      ellipse(
        left + blRadiusX,
        bottom - blRadiusY,
        blRadiusX,
        blRadiusY,
        0,
        1 * math.pi,
        0.5 * math.pi,
        true,
      );

      // Bottom side and bottom-right corner
      lineTo(right - brRadiusX, bottom);
      ellipse(
        right - brRadiusX,
        bottom - brRadiusY,
        brRadiusX,
        brRadiusY,
        0,
        0.5 * math.pi,
        0 * math.pi,
        true,
      );

      // Right side and top-right corner
      lineTo(right, top + trRadiusY);
      ellipse(
        right - trRadiusX,
        top + trRadiusY,
        trRadiusX,
        trRadiusY,
        0,
        0 * math.pi,
        1.5 * math.pi,
        true,
      );
    }
  }

  void beginPath();
  void moveTo(double x, double y);
  void lineTo(double x, double y);
  void ellipse(double centerX, double centerY, double radiusX, double radiusY,
      double rotation, double startAngle, double endAngle, bool antiClockwise);
}

/// Renders RRect to a 2d canvas.
class _RRectToCanvasRenderer extends _RRectRenderer {
  final html.CanvasRenderingContext2D context;
  _RRectToCanvasRenderer(this.context);
  void beginPath() {
    context.beginPath();
  }

  void moveTo(double x, double y) {
    context.moveTo(x, y);
  }

  void lineTo(double x, double y) {
    context.lineTo(x, y);
  }

  void ellipse(double centerX, double centerY, double radiusX, double radiusY,
      double rotation, double startAngle, double endAngle, bool antiClockwise) {
    DomRenderer.ellipse(context, centerX, centerY, radiusX, radiusY, rotation, startAngle,
        endAngle, antiClockwise);
  }
}

/// Renders RRect to a path.
class _RRectToPathRenderer extends _RRectRenderer {
  final ui.Path path;
  _RRectToPathRenderer(this.path);
  void beginPath() {}
  void moveTo(double x, double y) {
    path.moveTo(x, y);
  }

  void lineTo(double x, double y) {
    path.lineTo(x, y);
  }

  void ellipse(double centerX, double centerY, double radiusX, double radiusY,
      double rotation, double startAngle, double endAngle, bool antiClockwise) {
    path.addArc(
        ui.Rect.fromLTRB(centerX - radiusX, centerY - radiusY,
            centerX + radiusX, centerY + radiusY),
        startAngle,
        antiClockwise ? startAngle - endAngle : endAngle - startAngle);
  }
}

typedef RRectRendererEllipseCallback = void Function(double centerX, double centerY, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, bool antiClockwise);
typedef RRectRendererCallback = void Function(double x, double y);

/// Converts RRect to path primitives with callbacks.
class RRectMetricsRenderer extends _RRectRenderer {
  RRectMetricsRenderer({this.moveToCallback, this.lineToCallback, this.ellipseCallback});

  final RRectRendererEllipseCallback ellipseCallback;
  final RRectRendererCallback lineToCallback;
  final RRectRendererCallback moveToCallback;
  @override
  void beginPath() {}

  @override
  void ellipse(double centerX, double centerY, double radiusX, double radiusY, double rotation, double startAngle, double endAngle, bool antiClockwise) => ellipseCallback(
      centerX, centerY, radiusX, radiusY, rotation, startAngle, endAngle, antiClockwise);

  @override
  void lineTo(double x, double y) => lineToCallback(x, y);

  @override
  void moveTo(double x, double y) => moveToCallback(x, y);
}
