import Carbon
import Foundation

private let whitecoreSignature: OSType = 0x57434F52 // "WCOR"
private let exitIdentifier: UInt32 = 1
private let returnIdentifier: UInt32 = 2
private var exitRef: EventHotKeyRef?
private var returnRef: EventHotKeyRef?

private func signalPlayer(_ signal: String) {
    let task = Process()
    task.executableURL = URL(fileURLWithPath: "/usr/bin/pkill")
    task.arguments = ["-" + signal, "-x", "kraken-player"]
    try? task.run()
}

private func handleHotKey(
    _ nextHandler: EventHandlerCallRef?,
    _ event: EventRef?,
    _ userData: UnsafeMutableRawPointer?
) -> OSStatus {
    guard let event else { return OSStatus(eventNotHandledErr) }
    var identifier = EventHotKeyID()
    let status = GetEventParameter(
        event,
        EventParamName(kEventParamDirectObject),
        EventParamType(typeEventHotKeyID),
        nil,
        MemoryLayout<EventHotKeyID>.size,
        nil,
        &identifier
    )
    guard status == noErr else { return status }
    if identifier.id == exitIdentifier {
        signalPlayer("USR1")
    } else if identifier.id == returnIdentifier {
        signalPlayer("USR2")
    }
    return noErr
}

var eventSpec = EventTypeSpec(
    eventClass: OSType(kEventClassKeyboard),
    eventKind: UInt32(kEventHotKeyPressed)
)
var handlerRef: EventHandlerRef?
let handlerStatus = InstallEventHandler(
    GetApplicationEventTarget(),
    handleHotKey,
    1,
    &eventSpec,
    nil,
    &handlerRef
)
guard handlerStatus == noErr else {
    fputs("Whitecore hotkey handler failed: \(handlerStatus)\n", stderr)
    exit(1)
}

let modifiers = UInt32(controlKey | shiftKey)
let exitStatus = RegisterEventHotKey(
    UInt32(kVK_ANSI_Q), modifiers,
    EventHotKeyID(signature: whitecoreSignature, id: exitIdentifier),
    GetApplicationEventTarget(), 0, &exitRef
)
let returnStatus = RegisterEventHotKey(
    UInt32(kVK_ANSI_K), modifiers,
    EventHotKeyID(signature: whitecoreSignature, id: returnIdentifier),
    GetApplicationEventTarget(), 0, &returnRef
)
guard exitStatus == noErr && returnStatus == noErr else {
    fputs("Whitecore could not reserve Control+Shift+Q/K (\(exitStatus), \(returnStatus)).\n", stderr)
    exit(1)
}

_ = RunCurrentEventLoop(-1.0)
