import SwiftUI

/// Custom SwiftUI Shape that draws the characteristic MacBook notch outline.
/// Both top and bottom corner radii are animatable, enabling smooth transitions
/// between the compact closed state and the expanded open state.
///
/// The shape uses quadratic Bezier curves to produce the distinctive
/// top-edge cut-ins of the closed notch, and a clean rounded-bottom
/// rectangle when open (topCornerRadius approaches 0).
struct NotchShape: Shape {

    /// Radius applied to the top-left and top-right transitions where the notch
    /// curves away from the screen edge. When close to 0, the top corners become
    /// sharp and the shape is a rectangle with rounded bottom corners.
    var topCornerRadius: CGFloat

    /// Radius applied to the bottom-left and bottom-right inner corners.
    var bottomCornerRadius: CGFloat

    // MARK: - Animatable conformance

    var animatableData: AnimatablePair<CGFloat, CGFloat> {
        get { AnimatablePair(topCornerRadius, bottomCornerRadius) }
        set {
            topCornerRadius = newValue.first
            bottomCornerRadius = newValue.second
        }
    }

    // MARK: - Path

    func path(in rect: CGRect) -> Path {
        var path = Path()

        let minX = rect.minX
        let maxX = rect.maxX
        let minY = rect.minY
        let maxY = rect.maxY
        let width = rect.width
        let height = rect.height

        let topR = min(topCornerRadius, width / 4, height / 2)
        let botR = min(bottomCornerRadius, width / 4, height / 2)

        // Start at the top-left corner of the rect
        path.move(to: CGPoint(x: minX, y: minY))

        if topR > 0.5 {
            // Leave the screen edge horizontally, then turn into the side wall.
            path.addQuadCurve(
                to: CGPoint(x: minX + topR, y: minY + topR),
                control: CGPoint(x: minX + topR, y: minY)
            )
        } else {
            path.addLine(to: CGPoint(x: minX, y: minY))
        }

        // Left edge down to bottom-left corner area
        path.addLine(to: CGPoint(x: minX + topR, y: maxY - botR))

        // Bottom-left inner corner
        path.addQuadCurve(
            to: CGPoint(x: minX + topR + botR, y: maxY),
            control: CGPoint(x: minX + topR, y: maxY)
        )

        // Bottom edge across
        path.addLine(to: CGPoint(x: maxX - topR - botR, y: maxY))

        // Bottom-right inner corner
        path.addQuadCurve(
            to: CGPoint(x: maxX - topR, y: maxY - botR),
            control: CGPoint(x: maxX - topR, y: maxY)
        )

        // Right edge up to the top-right transition
        path.addLine(to: CGPoint(x: maxX - topR, y: minY + topR))

        if topR > 0.5 {
            // Mirror the top-left transition.
            path.addQuadCurve(
                to: CGPoint(x: maxX, y: minY),
                control: CGPoint(x: maxX - topR, y: minY)
            )
        } else {
            path.addLine(to: CGPoint(x: maxX, y: minY))
        }

        path.closeSubpath()
        return path
    }
}

// MARK: - Convenience initializers

extension NotchShape {

    /// Closed-state shape with tight corner radii that mimic the physical notch.
    static var closed: NotchShape {
        NotchShape(topCornerRadius: 6, bottomCornerRadius: 14)
    }

    /// Open-state shape: no top-edge cut-ins, just rounded bottom corners.
    /// topCornerRadius is near-zero so the top becomes effectively flat and the panel
    /// extends flush to the top edge of the screen.
    static var opened: NotchShape {
        NotchShape(topCornerRadius: 0, bottomCornerRadius: 24)
    }
}
