// 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 'dart:html' as html;
import 'dart:math' as math;

import 'package:ui/ui.dart' as ui;

import 'dom_renderer.dart';

/// Renders an RRect using path primitives.
abstract class RRectRenderer {
  // 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);
  @override
  void beginPath() {
    context.beginPath();
  }

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

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

  @override
  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);
  @override
  void beginPath() {}

  @override
  void moveTo(double x, double y) {
    path.moveTo(x, y);
  }

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

  @override
  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);
}
