// One workspace in the overview: a proportional card holding live thumbnails
// of its windows, labeled underneath. The focused workspace is outlined in the
// accent color, as GNOME outlines the current workspace.
//
// A card with a null `workspace` is the trailing "new workspace" affordance
// that dynamic-workspace setups (GNOME's, and Hyprland's) always show.

import Quickshell
import QtQuick
import qs.config

Item {
    id: root

    // HyprlandWorkspace, or null for the trailing "new workspace" card.
    required property var workspace
    // Shown on the empty trailing card.
    property int newWorkspaceId: 0

    property int refreshToken: 0
    // `emphasized` is the overview's current spatial selection. It normally
    // follows compositor focus, but can point at a requested focus workspace
    // before the user commits to switching there.
    property bool emphasized: focused
    property bool focusBound: false

    signal activated
    signal windowActivated(var toplevel)
    signal windowCloseRequested(var toplevel)
    signal windowDropped(var toplevel, string workspaceName)

    readonly property bool isNew: !workspace
    readonly property var windows: workspace ? workspace.toplevels.values : []
    readonly property bool focused: workspace ? workspace.focused : false
    readonly property string dropWorkspaceName: workspace ? String(workspace.id)
        : (newWorkspaceId > 0 ? String(newWorkspaceId) : "")

    readonly property string label: {
        if (isNew)
            return qsTr("New");
        // Named workspaces keep their name; numbered ones read better as
        // "Workspace N" only when there is room, so just show the name.
        return workspace.name ? workspace.name : String(workspace.id);
    }

    // Card body — the label sits under it, so reserve that space.
    readonly property int labelHeight: 22

    Rectangle {
        id: card
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: parent.bottom
        anchors.bottomMargin: root.labelHeight

        radius: Theme.cardRadius
        color: Theme.alpha(Theme.bgDark, 0.55)
        border.width: 2
        border.color: {
            if (dropArea.containsDrag)
                return Theme.ok;
            if (root.emphasized)
                return Theme.accent;
            if (root.focusBound)
                return Theme.alpha(Theme.accentSecondary, 0.72);
            return Theme.alpha(Theme.fg, 0.08);
        }

        Behavior on border.color {
            ColorAnimation {
                duration: Theme.durFast
            }
        }

        // Windows are laid out on a near-square grid. Hyprland does not expose
        // live per-window geometry, so an honest grid beats a wrong guess at
        // the real tiling.
        readonly property int columns: Math.max(1, Math.ceil(Math.sqrt(root.windows.length)))
        readonly property int rows: Math.max(1, Math.ceil(root.windows.length / columns))
        readonly property int cellW: Math.floor((width - Theme.itemSpacing * (columns + 1)) / columns)
        readonly property int cellH: Math.floor((height - Theme.itemSpacing * (rows + 1)) / rows)

        Grid {
            anchors.centerIn: parent
            columns: card.columns
            spacing: Theme.itemSpacing
            visible: root.windows.length > 0

            Repeater {
                model: root.windows

                WindowThumbnail {
                    required property var modelData
                    toplevel: modelData
                    refreshToken: root.refreshToken
                    width: card.cellW
                    height: card.cellH
                    onActivated: root.windowActivated(modelData)
                    onCloseRequested: root.windowCloseRequested(modelData)
                }
            }
        }

        DropArea {
            id: dropArea
            anchors.fill: parent
            z: 3
            enabled: root.dropWorkspaceName !== ""
            onDropped: drop => {
                if (!drop.source?.toplevel)
                    return;
                root.windowDropped(drop.source.toplevel, root.dropWorkspaceName);
                drop.acceptProposedAction();
            }
        }

        // Empty workspace: a big soft "+" so the card still reads as clickable.
        Text {
            anchors.centerIn: parent
            visible: root.windows.length === 0
            text: "+"
            color: Theme.alpha(Theme.fg, 0.25)
            font.family: Theme.fontFamily
            font.pixelSize: Math.max(Theme.fontSizeTitle, Math.round(card.height * 0.28))
        }

        Rectangle {
            anchors.top: parent.top
            anchors.right: parent.right
            anchors.margins: 8
            visible: root.focusBound
            width: focusBadge.implicitWidth + 16
            height: 24
            radius: Theme.pillRadius
            border.width: 0
            color: Theme.alpha(Theme.bgDark, 0.82)

            Row {
                id: focusBadge
                anchors.centerIn: parent
                spacing: 5

                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    text: "\u{F051F}"
                    color: Theme.accent
                    font.family: Theme.fontMono
                    font.pixelSize: 12
                }

                Text {
                    anchors.verticalCenter: parent.verticalCenter
                    text: "Focus"
                    color: Theme.fg
                    font.family: Theme.fontFamily
                    font.pixelSize: Theme.fontSizeSmall
                    font.weight: Font.Medium
                }
            }
        }

        // Sits below the thumbnails so clicking a window still focuses it.
        MouseArea {
            anchors.fill: parent
            z: -1
            onClicked: root.activated()
        }
    }

    Text {
        anchors.bottom: parent.bottom
        anchors.horizontalCenter: parent.horizontalCenter
        height: root.labelHeight
        verticalAlignment: Text.AlignVCenter
        text: root.label
        color: root.emphasized ? Theme.accent : Theme.fgDim
        font.family: Theme.fontFamily
        font.pixelSize: Theme.fontSize
        font.bold: root.emphasized
    }
}
