import AppKit

// MARK: - 通知名

extension Notification.Name {
    static let showSettingsPanel = Notification.Name("FloatingMonitor.ShowSettings")
    static let resizeMonitorWindow = Notification.Name("FloatingMonitor.ResizeWindow")
    static let refreshIntervalChanged = Notification.Name("FloatingMonitor.RefreshIntervalChanged")
}

// MARK: - AppDelegate

final class AppDelegate: NSObject, NSApplicationDelegate {
    private var windowController: FloatingWindowController?
    private var settingsWindowController: SettingsWindowController?
    private var statusItem: NSStatusItem?
    private var statusMenu: NSMenu!

    let systemMonitor = SystemMonitor()

    func applicationDidFinishLaunching(_ notification: Notification) {
        NSApp.setActivationPolicy(.accessory)

        windowController = FloatingWindowController()
        let contentView = ContentView(monitor: systemMonitor, windowController: windowController)
        windowController?.embed(rootView: contentView)

        let cfg = Configuration.shared
        windowController?.resize(width: cfg.windowWidth, height: cfg.windowHeight)

        systemMonitor.interval = cfg.refreshInterval
        systemMonitor.topN = cfg.processCount
        systemMonitor.start()

        setupStatusItem()
        observeResize()
    }

    // MARK: - 菜单栏

    private func setupStatusItem() {
        statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
        guard let button = statusItem?.button else { return }

        if let image = NSImage(systemSymbolName: "gauge.with.dots.needle.33percent",
                               accessibilityDescription: "Monitor") {
            image.isTemplate = true
            button.image = image
        }
        button.toolTip = "Monitor"

        statusMenu = NSMenu()

        let toggleItem = NSMenuItem(title: "显示 Monitor", action: #selector(menuToggleWindow), keyEquivalent: "")
        toggleItem.target = self
        statusMenu.addItem(toggleItem)
        statusMenu.addItem(.separator())

        let settingsItem = NSMenuItem(title: "显示设置…", action: #selector(menuOpenSettings), keyEquivalent: ",")
        settingsItem.keyEquivalentModifierMask = .command
        settingsItem.target = self
        statusMenu.addItem(settingsItem)
        statusMenu.addItem(.separator())

        let quitItem = NSMenuItem(title: "退出 Monitor", action: #selector(menuQuit), keyEquivalent: "q")
        quitItem.keyEquivalentModifierMask = .command
        quitItem.target = self
        statusMenu.addItem(quitItem)

        statusItem?.menu = statusMenu

        button.target = self
        button.action = #selector(statusItemClicked)
        button.sendAction(on: [.leftMouseDown, .rightMouseDown])
    }

    @objc private func statusItemClicked() {
        guard let event = NSApp.currentEvent else { return }
        if event.type == .rightMouseDown {
            updateToggleMenuItemTitle()
        } else {
            toggleWindow()
        }
    }

    @objc private func menuToggleWindow() { toggleWindow() }
    @objc private func toggleWindow() { windowController?.toggleVisible() }
    @objc private func menuOpenSettings() { openSettingsWindow() }
    @objc private func menuQuit() { NSApp.terminate(nil) }

    private func updateToggleMenuItemTitle() {
        let visible = windowController?.isVisible ?? false
        statusMenu.item(at: 0)?.title = visible ? "隐藏 Monitor" : "显示 Monitor"
    }

    // MARK: - 设置窗口

    private func openSettingsWindow() {
        if settingsWindowController == nil {
            settingsWindowController = SettingsWindowController(monitor: systemMonitor)
        }
        settingsWindowController?.show()
    }

    // MARK: - 监听

    private func observeResize() {
        NotificationCenter.default.addObserver(
            forName: .resizeMonitorWindow, object: nil, queue: .main
        ) { [weak self] notification in
            guard let size = notification.object as? NSSize else { return }
            self?.windowController?.resize(width: size.width, height: size.height)
        }
    }

    func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool {
        windowController?.show()
        return true
    }
}
