import Foundation

public struct ShortcutModifiers: OptionSet, Equatable, Sendable {
    public let rawValue: UInt

    public init(rawValue: UInt) {
        self.rawValue = rawValue
    }

    public static let option = ShortcutModifiers(rawValue: 1 << 0)
    public static let command = ShortcutModifiers(rawValue: 1 << 1)
    public static let shift = ShortcutModifiers(rawValue: 1 << 2)
    public static let control = ShortcutModifiers(rawValue: 1 << 3)
}

public struct KeyboardShortcut: Equatable, Sendable {
    public let keyCode: UInt16
    public let modifiers: ShortcutModifiers

    public init(keyCode: UInt16, modifiers: ShortcutModifiers) {
        self.keyCode = keyCode
        self.modifiers = modifiers
    }
}

public enum TriggerKeyCode {
    public static let tab: UInt16 = 48
    public static let escape: UInt16 = 53
    public static let returnKey: UInt16 = 36
    public static let keypadEnter: UInt16 = 76
    public static let leftArrow: UInt16 = 123
    public static let rightArrow: UInt16 = 124
    public static let downArrow: UInt16 = 125
    public static let upArrow: UInt16 = 126
}

public enum TriggerDefaults {
    public static let quickSwitchShortcut = KeyboardShortcut(
        keyCode: TriggerKeyCode.tab,
        modifiers: [.option]
    )

    public static let forceQuitShortcut = KeyboardShortcut(
        keyCode: TriggerKeyCode.escape,
        modifiers: [.command, .option]
    )
}

public enum TriggerEventDecision: Equatable, Sendable {
    case quickSwitch(consumeEvent: Bool)
    case passThrough
}

public enum TriggerEventPolicy {
    public static func decision(
        for shortcut: KeyboardShortcut,
        configuredQuickSwitch: KeyboardShortcut = TriggerDefaults.quickSwitchShortcut,
        overlayVisible: Bool,
        consumeInitialQuickSwitch: Bool = false
    ) -> TriggerEventDecision {
        guard shortcut != TriggerDefaults.forceQuitShortcut else {
            return .passThrough
        }

        guard shortcut == configuredQuickSwitch else {
            return .passThrough
        }

        return .quickSwitch(consumeEvent: overlayVisible || consumeInitialQuickSwitch)
    }
}

@MainActor
public final class ManualTriggerService: TriggerServiceProtocol {
    public var onQuickSwitch: (() -> Void)?
    public private(set) var isRunning = false

    public init() {}

    public func start() {
        isRunning = true
    }

    public func stop() {
        isRunning = false
    }

    public func triggerQuickSwitch() {
        guard isRunning else { return }
        onQuickSwitch?()
    }
}
