import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Wayland
import ".."

PanelWindow {
    id: notificationLayer

    anchors {
        top: true
        right: true
    }

    margins {
        top: theme.panelMarginTop
        right: theme.panelMarginRight
    }

    // Match the media status overlay behavior so notifications stay visible
    // even when an app is fullscreen.
    WlrLayershell.layer: WlrLayer.Overlay
    WlrLayershell.focusable: false
    WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
    WlrLayershell.namespace: "deltarune-quickshell-notifications"

    exclusionMode: ExclusionMode.Ignore
    aboveWindows: true
    focusable: false
    visible: true
    color: "#00000000"

    NotificationTheme {
        id: theme
    }

    property int stackWidth: theme.stackWidth
    property int menuReservedHeight: theme.topbarReservedHeight
    readonly property bool stackPreviewEnabled: Boolean(ShellStateManager.global("notifications.stackPreviewEnabled", true))

    readonly property int screenHeight: screen ? screen.height : 1080
    readonly property bool topbarOpen: ShellStateManager.shellOpen
    readonly property int stackOffsetY: topbarOpen ? menuReservedHeight + theme.panelMarginTop : 0
    readonly property int maxStackHeight: Math.max(120, screenHeight - theme.panelMarginTop - stackOffsetY - theme.panelMarginTop)

    implicitWidth: stackWidth
    implicitHeight: stackOffsetY + notificationViewport.height

    // Input handling decision: the layer itself never grabs focus and is only
    // as large as the stack. This keeps the container effectively click-through
    // outside notification bounds and avoids any global pointer/keyboard grabs.
    mask: Region {
        item: notificationViewport
    }

    NotificationModel {
        id: notificationModel
    }

    Flickable {
        id: notificationViewport
        x: 0
        y: notificationLayer.stackOffsetY
        width: notificationLayer.stackWidth
        height: Math.min(notificationColumn.implicitHeight, notificationLayer.maxStackHeight)
        clip: true
        boundsBehavior: Flickable.StopAtBounds
        contentWidth: width
        contentHeight: notificationColumn.implicitHeight
        interactive: contentHeight > height
        flickableDirection: Flickable.VerticalFlick

        WheelHandler {
            acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad
            onWheel: function (event) {
                if (!notificationViewport.interactive)
                    return;
                const step = event.angleDelta.y / 120 * 60;
                notificationViewport.contentY = Math.max(0, Math.min(notificationViewport.contentHeight - notificationViewport.height, notificationViewport.contentY - step));
                event.accepted = true;
            }
        }

        ScrollBar.vertical: ScrollBar {
            policy: notificationViewport.interactive ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
            width: 6
        }

        Column {
            id: notificationColumn
            width: notificationViewport.width
            spacing: 0

            Repeater {
                model: notificationModel.groupedNotifications

                NotificationGroup {
                    theme: theme
                    groupData: modelData
                    expanded: notificationModel.groupIsExpanded(modelData.groupKey)
                    peekEnabled: notificationLayer.stackPreviewEnabled

                    width: notificationLayer.stackWidth

                    onExpandRequested: function (groupKey, shouldExpand) {
                        notificationModel.setGroupExpanded(groupKey, shouldExpand);
                    }

                    onCloseFinished: function (closedNotificationId, reason) {
                        notificationModel.closeById(closedNotificationId, reason);
                    }
                }
            }
        }
    }
}
