import CoreGraphics
import Foundation

func usage() -> Never {
    FileHandle.standardError.write(
        Data("usage: round1-visible-owner-window-sampler.swift <owner-name> <duration-seconds> <interval-seconds> <output-path>\n".utf8)
    )
    exit(2)
}

let args = CommandLine.arguments
guard args.count == 5,
      let duration = Double(args[2]),
      let interval = Double(args[3]),
      duration > 0,
      interval > 0 else {
    usage()
}

let ownerName = args[1]
let outputPath = args[4]
let deadline = Date().addingTimeInterval(duration)
var sampleCount = 0

func describe(_ item: [String: Any]) -> String {
    let title = item[kCGWindowName as String] as? String ?? ""
    let layer = item[kCGWindowLayer as String] as? Int ?? 0
    let number = item[kCGWindowNumber as String] as? Int ?? 0
    let bounds = item[kCGWindowBounds as String] as? [String: Any] ?? [:]
    return "windowNumber=\(number) title=\"\(title)\" layer=\(layer) bounds=\(bounds)"
}

func writeReport(_ text: String) {
    do {
        try text.write(toFile: outputPath, atomically: true, encoding: .utf8)
    } catch {
        FileHandle.standardError.write(Data("failed to write sampler report: \(error)\n".utf8))
    }
}

repeat {
    sampleCount += 1
    let windows = CGWindowListCopyWindowInfo([.optionOnScreenOnly, .excludeDesktopElements], kCGNullWindowID) as? [[String: Any]] ?? []
    let matches = windows
        .filter { item in
            (item[kCGWindowOwnerName as String] as? String) == ownerName
        }
        .map(describe)

    if !matches.isEmpty {
        let report = """
        owner=\(ownerName)
        samples=\(sampleCount)
        visibleWindows=\(matches.count)
        \(matches.joined(separator: "\n"))
        """
        writeReport(report + "\n")
        print(report)
        exit(1)
    }

    if Date() < deadline {
        Thread.sleep(forTimeInterval: interval)
    }
} while Date() < deadline

let report = "owner=\(ownerName) samples=\(sampleCount) visibleWindows=0 duration=\(duration) interval=\(interval)"
writeReport(report + "\n")
print(report)
