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