import Foundation
import CoreGraphics

struct AppSettings: Equatable, Codable {
    var display: DisplaySettings
    var behavior: BehaviorSettings
    var appearance: AppearanceSettings
    var animation: AnimationSettings
    var terminal: TerminalSettings
    var hotkeys: HotkeySettings

    static let `default` = AppSettings(
        display: DisplaySettings(
            showOnAllDisplays: NotchSettings.Defaults.showOnAllDisplays,
            showMenuBarIcon: NotchSettings.Defaults.showMenuBarIcon,
            launchAtLogin: NotchSettings.Defaults.launchAtLogin,
            notchHeightMode: NotchSettings.Defaults.notchHeightMode,
            notchHeight: NotchSettings.Defaults.notchHeight,
            nonNotchHeightMode: NotchSettings.Defaults.nonNotchHeightMode,
            nonNotchHeight: NotchSettings.Defaults.nonNotchHeight,
            openWidth: NotchSettings.Defaults.openWidth,
            openHeight: NotchSettings.Defaults.openHeight
        ),
        behavior: BehaviorSettings(
            openNotchOnHover: NotchSettings.Defaults.openNotchOnHover,
            minimumHoverDuration: NotchSettings.Defaults.minimumHoverDuration,
            enableGestures: NotchSettings.Defaults.enableGestures,
            gestureSensitivity: NotchSettings.Defaults.gestureSensitivity
        ),
        appearance: AppearanceSettings(
            enableShadow: NotchSettings.Defaults.enableShadow,
            shadowRadius: NotchSettings.Defaults.shadowRadius,
            shadowOpacity: NotchSettings.Defaults.shadowOpacity,
            cornerRadiusScaling: NotchSettings.Defaults.cornerRadiusScaling,
            notchOpacity: NotchSettings.Defaults.notchOpacity,
            blurRadius: NotchSettings.Defaults.blurRadius
        ),
        animation: AnimationSettings(
            openSpringResponse: NotchSettings.Defaults.openSpringResponse,
            openSpringDamping: NotchSettings.Defaults.openSpringDamping,
            closeSpringResponse: NotchSettings.Defaults.closeSpringResponse,
            closeSpringDamping: NotchSettings.Defaults.closeSpringDamping,
            hoverSpringResponse: NotchSettings.Defaults.hoverSpringResponse,
            hoverSpringDamping: NotchSettings.Defaults.hoverSpringDamping,
            resizeAnimationDuration: NotchSettings.Defaults.resizeAnimationDuration
        ),
        terminal: TerminalSettings(
            fontSize: NotchSettings.Defaults.terminalFontSize,
            shellPath: NotchSettings.Defaults.terminalShell,
            themeRawValue: NotchSettings.Defaults.terminalTheme,
            sizePresetsJSON: NotchSettings.Defaults.terminalSizePresets
        ),
        hotkeys: HotkeySettings(
            toggle: .cmdReturn,
            newTab: .cmdT,
            closeTab: .cmdW,
            nextTab: .cmdShiftRB,
            previousTab: .cmdShiftLB,
            nextWorkspace: .cmdShiftDown,
            previousWorkspace: .cmdShiftUp,
            detachTab: .cmdD
        )
    )
}

extension AppSettings {
    struct DisplaySettings: Equatable, Codable {
        var showOnAllDisplays: Bool
        var showMenuBarIcon: Bool
        var launchAtLogin: Bool
        var notchHeightMode: Int
        var notchHeight: Double
        var nonNotchHeightMode: Int
        var nonNotchHeight: Double
        var openWidth: Double
        var openHeight: Double
    }

    struct BehaviorSettings: Equatable, Codable {
        var openNotchOnHover: Bool
        var minimumHoverDuration: Double
        var enableGestures: Bool
        var gestureSensitivity: Double
    }

    struct AppearanceSettings: Equatable, Codable {
        var enableShadow: Bool
        var shadowRadius: Double
        var shadowOpacity: Double
        var cornerRadiusScaling: Bool
        var notchOpacity: Double
        var blurRadius: Double
    }

    struct AnimationSettings: Equatable, Codable {
        var openSpringResponse: Double
        var openSpringDamping: Double
        var closeSpringResponse: Double
        var closeSpringDamping: Double
        var hoverSpringResponse: Double
        var hoverSpringDamping: Double
        var resizeAnimationDuration: Double
    }

    struct TerminalSettings: Equatable, Codable {
        var fontSize: Double
        var shellPath: String
        var themeRawValue: String
        var sizePresetsJSON: String

        var theme: TerminalTheme {
            TerminalTheme.resolve(themeRawValue)
        }

        var sizePresets: [TerminalSizePreset] {
            TerminalSizePresetStore.decodePresets(from: sizePresetsJSON) ?? TerminalSizePresetStore.loadDefaults()
        }
    }

    struct HotkeySettings: Equatable, Codable {
        var toggle: HotkeyBinding
        var newTab: HotkeyBinding
        var closeTab: HotkeyBinding
        var nextTab: HotkeyBinding
        var previousTab: HotkeyBinding
        var nextWorkspace: HotkeyBinding
        var previousWorkspace: HotkeyBinding
        var detachTab: HotkeyBinding
    }
}

extension AppSettings.DisplaySettings {
    struct LayoutSignature: Equatable {
        var notchHeightMode: Int
        var notchHeight: Double
        var nonNotchHeightMode: Int
        var nonNotchHeight: Double
        var openWidth: Double
        var openHeight: Double
    }

    var layoutSignature: LayoutSignature {
        LayoutSignature(
            notchHeightMode: notchHeightMode,
            notchHeight: notchHeight,
            nonNotchHeightMode: nonNotchHeightMode,
            nonNotchHeight: nonNotchHeight,
            openWidth: openWidth,
            openHeight: openHeight
        )
    }
}

struct TerminalSessionConfiguration: Equatable {
    var fontSize: CGFloat
    var theme: TerminalTheme
    var shellPath: String
}

@MainActor
protocol TerminalSessionConfigurationProviding: AnyObject {
    var terminalSessionConfiguration: TerminalSessionConfiguration { get }
    var hotkeySettings: AppSettings.HotkeySettings { get }
    var terminalSizePresets: [TerminalSizePreset] { get }
}
