//  🖥️ TUIKit — Terminal UI Kit for Swift
//  OverlayModifier.swift
//
//  Created by LAYERED.work
//  License: MIT

/// Internal modifier that layers an overlay view on top of the base content.
///
/// The overlay is rendered on top of the base content. Both views are rendered
/// to their natural size, and the overlay is positioned according to the
/// specified alignment within the base content's bounds.
public struct OverlayModifier<Base: View, Overlay: View>: View {
    /// The base content.
    let base: Base

    /// The overlay content.
    let overlay: Overlay

    /// The alignment of the overlay within the base bounds.
    let alignment: Alignment

    public var body: Never {
        fatalError("OverlayModifier renders via Renderable")
    }
}

// MARK: - Equatable Conformance

extension OverlayModifier: @preconcurrency Equatable where Base: Equatable, Overlay: Equatable {
    public static func == (lhs: OverlayModifier<Base, Overlay>, rhs: OverlayModifier<Base, Overlay>) -> Bool {
        lhs.base == rhs.base &&
        lhs.overlay == rhs.overlay &&
        lhs.alignment == rhs.alignment
    }
}

// MARK: - Renderable

extension OverlayModifier: Renderable {
    public func renderToBuffer(context: RenderContext) -> FrameBuffer {
        // Render both contents
        let baseBuffer = TUIkit.renderToBuffer(base, context: context)
        let overlayBuffer = TUIkit.renderToBuffer(overlay, context: context)

        guard !baseBuffer.isEmpty else {
            return overlayBuffer
        }

        guard !overlayBuffer.isEmpty else {
            return baseBuffer
        }

        // Calculate the position of the overlay based on alignment
        let baseWidth = baseBuffer.width
        let baseHeight = baseBuffer.height
        let overlayWidth = overlayBuffer.width
        let overlayHeight = overlayBuffer.height

        // Calculate horizontal position
        let horizontalOffset: Int
        switch alignment.horizontal {
        case .leading:
            horizontalOffset = 0
        case .center:
            horizontalOffset = max(0, (baseWidth - overlayWidth) / 2)
        case .trailing:
            horizontalOffset = max(0, baseWidth - overlayWidth)
        }

        // Calculate vertical position
        let verticalOffset: Int
        switch alignment.vertical {
        case .top:
            verticalOffset = 0
        case .center:
            verticalOffset = max(0, (baseHeight - overlayHeight) / 2)
        case .bottom:
            verticalOffset = max(0, baseHeight - overlayHeight)
        }

        // Composite the overlay onto the base
        return baseBuffer.composited(with: overlayBuffer, at: (x: horizontalOffset, y: verticalOffset))
    }
}
