import CoreGraphics
import Foundation

public struct OverlayScreenSpaceState: Equatable, Sendable {
    public static let unknown = OverlayScreenSpaceState(isFullscreenSpace: false, isSplitViewSpace: false)

    public let isFullscreenSpace: Bool
    public let isSplitViewSpace: Bool

    public init(isFullscreenSpace: Bool = false, isSplitViewSpace: Bool = false) {
        self.isFullscreenSpace = isFullscreenSpace
        self.isSplitViewSpace = isSplitViewSpace
    }
}

public struct OverlayScreenRecord: Equatable, Sendable {
    public let displayUUID: String
    public let frame: CGRect
    public let visibleFrame: CGRect
    public let isFullscreenSpace: Bool
    public let isSplitViewSpace: Bool

    public init(
        displayUUID: String,
        frame: CGRect,
        visibleFrame: CGRect,
        isFullscreenSpace: Bool = false,
        isSplitViewSpace: Bool = false
    ) {
        self.displayUUID = displayUUID
        self.frame = frame
        self.visibleFrame = visibleFrame
        self.isFullscreenSpace = isFullscreenSpace
        self.isSplitViewSpace = isSplitViewSpace
    }

    public init(
        displayUUID: String,
        frame: CGRect,
        visibleFrame: CGRect,
        spaceState: OverlayScreenSpaceState
    ) {
        self.init(
            displayUUID: displayUUID,
            frame: frame,
            visibleFrame: visibleFrame,
            isFullscreenSpace: spaceState.isFullscreenSpace,
            isSplitViewSpace: spaceState.isSplitViewSpace
        )
    }
}

public struct OverlayPlacementContext: Equatable, Sendable {
    public let targetDisplayUUID: String?
    public let targetFrame: CGRect?
    public let mouseLocation: CGPoint
    public let coverFullscreenSpace: Bool
    public let isFullscreenSpace: Bool
    public let isSplitViewSpace: Bool
    public let avoidSpaceSwitch: Bool

    public init(
        targetDisplayUUID: String?,
        targetFrame: CGRect?,
        mouseLocation: CGPoint,
        coverFullscreenSpace: Bool = true,
        isFullscreenSpace: Bool = false,
        isSplitViewSpace: Bool = false,
        avoidSpaceSwitch: Bool = true
    ) {
        self.targetDisplayUUID = targetDisplayUUID
        self.targetFrame = targetFrame
        self.mouseLocation = mouseLocation
        self.coverFullscreenSpace = coverFullscreenSpace
        self.isFullscreenSpace = isFullscreenSpace
        self.isSplitViewSpace = isSplitViewSpace
        self.avoidSpaceSwitch = avoidSpaceSwitch
    }

    public var overlayContext: OverlayContext {
        OverlayContext(
            entryPoint: .quickSwitch,
            spacePolicy: SpacePolicy(isFullscreenSpace: isFullscreenSpace, avoidSpaceSwitch: avoidSpaceSwitch),
            targetDisplayUUID: targetDisplayUUID
        )
    }
}

public enum OverlayPlacementPolicy {
    public static func placement(
        forMouseLocation mouseLocation: CGPoint,
        screens: [OverlayScreenRecord]
    ) -> OverlayPlacementContext {
        let targetScreen = screen(containing: mouseLocation, screens: screens) ?? screens.first

        return OverlayPlacementContext(
            targetDisplayUUID: targetScreen?.displayUUID,
            targetFrame: targetScreen?.frame,
            mouseLocation: mouseLocation,
            coverFullscreenSpace: true,
            isFullscreenSpace: targetScreen?.isFullscreenSpace ?? false,
            isSplitViewSpace: targetScreen?.isSplitViewSpace ?? false,
            avoidSpaceSwitch: true
        )
    }

    private static func screen(
        containing point: CGPoint,
        screens: [OverlayScreenRecord]
    ) -> OverlayScreenRecord? {
        screens.first { screen in
            screen.frame.contains(point)
        }
    }
}
