//
//  SpeedKeysApp.swift
//  SpeedKeys
//
//  Created by Jose Polo Ramos on 2/24/25.
//

import SwiftUI
import Foundation

/// Global keyboard event handler that intercepts key presses system-wide
/// This function is called whenever a keyboard event occurs
/// - Parameters:
///   - proxy: The event tap proxy for the event
///   - type: The type of event (keyDown, keyUp, etc.)
///   - event: The actual keyboard event containing key information
///   - data: Optional user data passed to the event tap
/// - Returns: The event (either modified or unmodified) to pass along the event chain
func handleKeyTap(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, data: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? {
 
    // Only process key down events
    if [.keyDown].contains(type) {
   
        // Convert the keyboard event into a ShortCuts object
        let s = ShortCuts(event: event)

        // Look up if this shortcut has a corresponding entry in our database
        guard let e: Entry = Entries.entry(fromShortCut: s.description) else {
            // If no entry found, pass the event through unmodified
            return Unmanaged.passUnretained(event)
        }

        // Create a new process to execute the command/open the application
        let process = Process()
        
        // Set up pipe to capture output and errors
        let pipe = Pipe()
        process.standardOutput = pipe
        process.standardError = pipe
        
        // Build the command: either use custom command or default "open" command
        // Default format: "open [path] -a [app]"
        let command = e.command.isEmpty ? ["open", e.path, "-a", e.app].joined(separator: " ") : e.command
        
        // Execute command through zsh shell
        process.launchPath = "/bin/zsh"
        process.arguments = ["-c", command]
        
        // Launch the process (macOS version-specific API)
        if #available(macOS 13.0, *) {
           try! process.run()
         } else {
           process.launch()
         }
        
        // Read and print the command output
        let data = pipe.fileHandleForReading.readDataToEndOfFile()
        let output = String(data: data, encoding: .utf8) ?? ""
        print("output: \(output)")
    }

    // Pass the event through to other handlers
    return Unmanaged.passUnretained(event)
}

/// Main application struct for SpeedKeys
/// A menu bar app that intercepts keyboard shortcuts and executes custom commands
@main
struct SpeedKeysApp: App {
    
    // Current number displayed in menu bar (currently unused in logic)
    @State var currentNumber: String = "1"
    
    // Environment actions for window management
    @Environment(\.openWindow) private var openWindow
    @Environment(\.dismissWindow) private var dismissWindow
    
    // Singleton instance of entries data
    var entries: Entries = Entries.instance
    
    // Tracks whether the main window is currently open
    @State private var isWindowOpen = false
    
    /// Initializer that sets up system-wide keyboard event monitoring
    /// Requests accessibility permissions and creates an event tap
    init() {
        // Request accessibility permissions (required for global keyboard monitoring)
        let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeUnretainedValue() as String : true]
        let accessEnabled = AXIsProcessTrustedWithOptions(options)

        if !accessEnabled {
            print("Access Not Enabled")
            return
        }
        
        // Create event mask for keyboard events we want to monitor
        // Monitors both keyDown events and modifier key changes
        let keyboardEventMask = CGEventMask((1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.flagsChanged.rawValue))
        
        // Create the event tap that intercepts keyboard events
        guard let eventTap = CGEvent.tapCreate(
            tap: .cgSessionEventTap,              // Monitor all events in user session
            place: .headInsertEventTap,           // Insert at beginning of event chain
            options: .defaultTap,                 // Standard event tap
            eventsOfInterest: keyboardEventMask,  // Only keyboard events
            callback: { proxy, type, event, refcon in
                return handleKeyTap(proxy: proxy, type: type, event: event, data: refcon)
            },
            userInfo: nil)
        else {
            print("failed to create tap")
            return
        }
        
        // Add event tap to the run loop so it processes events
        let runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0)
        CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, .commonModes)
        
        // Enable the event tap
        CGEvent.tapEnable(tap: eventTap, enable: true)
    }
    
    var body: some Scene {
        
        // Create menu bar extra (icon in system menu bar)
        MenuBarExtra(currentNumber, image: "AppPanelIcon") {

            // Toggle main window visibility
            Button(action: {
                if isWindowOpen {
                    dismissWindow(id: "main")
                    isWindowOpen = false
                } else {
                    openWindow(id: "main")
                    isWindowOpen = true
                }
            }) {
                Label(isWindowOpen ? "Hide Window" : "Show Window", image: "list.bullet.rectangle.fill")
            }
            .keyboardShortcut("w")
            
            // Show help (currently no action)
            Button(action: {}) {
                Label("Show Help", image: "questionmark.circle.fill")
            }
            .keyboardShortcut("q")
            
            Divider()
            
            // Quit application
            Button(action: {
                NSApplication.shared.terminate(nil)
            }) {
                Label("Quit", image: "arrow.down.right.and.arrow.up.left")
            }
            .keyboardShortcut("q")
        }
        
        // Main application window (toggled via menu bar)
        WindowGroup(id: "main") {
            ContentView(selected: "")
                .frame(minWidth: 1580, minHeight: 800)
        }
        .defaultSize(width: 1580, height: 800)
        .windowStyle(.hiddenTitleBar)           // Hide standard title bar
        .windowResizability(.contentSize)        // Window can be resized
        .defaultPosition(.center)                // Center on screen
        // .windowLevel(.floating)               // Keep window above others (commented out)
        .handlesExternalEvents(matching: ["main"]) // Handle external window requests
    }
}
