// Copyright 2014 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:math' as math;

import 'basic_types.dart';
import 'borders.dart';

/// A shape with a notch in its outline.
///
/// Typically used as the outline of a 'host' widget to make a notch that
/// accommodates a 'guest' widget. e.g the [BottomAppBar] may have a notch to
/// accommodate the [FloatingActionButton].
///
/// See also:
///
///  * [ShapeBorder], which defines a shaped border without a dynamic notch.
///  * [AutomaticNotchedShape], an adapter from [ShapeBorder] to [NotchedShape].
abstract class NotchedShape {
  /// Abstract const constructor. This constructor enables subclasses to provide
  /// const constructors so that they can be used in const expressions.
  const NotchedShape();

  /// Creates a [Path] that describes the outline of the shape.
  ///
  /// The `host` is the bounding rectangle of the shape.
  ///
  /// The `guest` is the bounding rectangle of the shape for which a notch will
  /// be made. It is null when there is no guest.
  Path getOuterPath(Rect host, Rect? guest);
}

/// A rectangle with a smooth circular notch.
///
/// See also:
///
///  * [CircleBorder], a [ShapeBorder] that describes a circle.
class CircularNotchedRectangle extends NotchedShape {
  /// Creates a [CircularNotchedRectangle].
  ///
  /// The same object can be used to create multiple shapes.
  const CircularNotchedRectangle();

  /// Creates a [Path] that describes a rectangle with a smooth circular notch.
  ///
  /// `host` is the bounding box for the returned shape. Conceptually this is
  /// the rectangle to which the notch will be applied.
  ///
  /// `guest` is the bounding box of a circle that the notch accommodates. All
  /// points in the circle bounded by `guest` will be outside of the returned
  /// path.
  ///
  /// The notch is curve that smoothly connects the host's top edge and
  /// the guest circle.
  // TODO(amirh): add an example diagram here.
  @override
  Path getOuterPath(Rect host, Rect? guest) {
    if (guest == null || !host.overlaps(guest))
      return Path()..addRect(host);

    // The guest's shape is a circle bounded by the guest rectangle.
    // So the guest's radius is half the guest width.
    final double notchRadius = guest.width / 2.0;

    // We build a path for the notch from 3 segments:
    // Segment A - a Bezier curve from the host's top edge to segment B.
    // Segment B - an arc with radius notchRadius.
    // Segment C - a Bezier curve from segment B back to the host's top edge.
    //
    // A detailed explanation and the derivation of the formulas below is
    // available at: https://goo.gl/Ufzrqn

    const double s1 = 15.0;
    const double s2 = 1.0;

    final double r = notchRadius;
    final double a = -1.0 * r - s2;
    final double b = host.top - guest.center.dy;

    final double n2 = math.sqrt(b * b * r * r * (a * a + b * b - r * r));
    final double p2xA = ((a * r * r) - n2) / (a * a + b * b);
    final double p2xB = ((a * r * r) + n2) / (a * a + b * b);
    final double p2yA = math.sqrt(r * r - p2xA * p2xA);
    final double p2yB = math.sqrt(r * r - p2xB * p2xB);

    final List<Offset?> p = List<Offset?>.filled(6, null);

    // p0, p1, and p2 are the control points for segment A.
    p[0] = Offset(a - s1, b);
    p[1] = Offset(a, b);
    final double cmp = b < 0 ? -1.0 : 1.0;
    p[2] = cmp * p2yA > cmp * p2yB ? Offset(p2xA, p2yA) : Offset(p2xB, p2yB);

    // p3, p4, and p5 are the control points for segment B, which is a mirror
    // of segment A around the y axis.
    p[3] = Offset(-1.0 * p[2]!.dx, p[2]!.dy);
    p[4] = Offset(-1.0 * p[1]!.dx, p[1]!.dy);
    p[5] = Offset(-1.0 * p[0]!.dx, p[0]!.dy);

    // translate all points back to the absolute coordinate system.
    for (int i = 0; i < p.length; i += 1)
      p[i] = p[i]! + guest.center;

    return Path()
      ..moveTo(host.left, host.top)
      ..lineTo(p[0]!.dx, p[0]!.dy)
      ..quadraticBezierTo(p[1]!.dx, p[1]!.dy, p[2]!.dx, p[2]!.dy)
      ..arcToPoint(
        p[3]!,
        radius: Radius.circular(notchRadius),
        clockwise: false,
      )
      ..quadraticBezierTo(p[4]!.dx, p[4]!.dy, p[5]!.dx, p[5]!.dy)
      ..lineTo(host.right, host.top)
      ..lineTo(host.right, host.bottom)
      ..lineTo(host.left, host.bottom)
      ..close();
  }
}

/// A [NotchedShape] created from [ShapeBorder]s.
///
/// Two shapes can be provided. The [host] is the shape of the widget that
/// uses the [NotchedShape] (typically a [BottomAppBar]). The [guest] is
/// subtracted from the [host] to create the notch (typically to make room
/// for a [FloatingActionButton]).
class AutomaticNotchedShape extends NotchedShape {
  /// Creates a [NotchedShape] that is defined by two [ShapeBorder]s.
  ///
  /// The [host] must not be null.
  ///
  /// The [guest] may be null, in which case no notch is created even
  /// if a guest rectangle is provided to [getOuterPath].
  const AutomaticNotchedShape(this.host, [ this.guest ]);

  /// The shape of the widget that uses the [NotchedShape] (typically a
  /// [BottomAppBar]).
  ///
  /// This shape cannot depend on the [TextDirection], as no text direction
  /// is available to [NotchedShape]s.
  final ShapeBorder host;

  /// The shape to subtract from the [host] to make the notch.
  ///
  /// This shape cannot depend on the [TextDirection], as no text direction
  /// is available to [NotchedShape]s.
  ///
  /// If this is null, [getOuterPath] ignores the guest rectangle.
  final ShapeBorder? guest;

  @override
  Path getOuterPath(Rect hostRect, Rect? guestRect) { // ignore: avoid_renaming_method_parameters
    // The parameters of this method are renamed over the baseclass because they
    // would clash with properties of this object, and the use of all four of
    // them in the code below is really confusing if they have the same names.
    final Path hostPath = host.getOuterPath(hostRect);
    if (guest != null && guestRect != null) {
      final Path guestPath = guest!.getOuterPath(guestRect);
      return Path.combine(PathOperation.difference, hostPath, guestPath);
    }
    return hostPath;
  }
}
