/*
    KWin - the KDE window manager
    This file is part of the KDE project.

    SPDX-FileCopyrightText: 2012, 2013 Martin Gräßlin <mgraesslin@kde.org>

    SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick
import QtQuick.Window
import org.kde.plasma.core as PlasmaCore
import org.kde.kirigami 2.20 as Kirigami
import org.kde.ksvg 1.0 as KSvg
import org.kde.kwin

PlasmaCore.Window {
    id: dialog
    visible: false
    flags: Qt.X11BypassWindowManagerHint | Qt.FramelessWindowHint

    width: mainItem.implicitWidth + leftPadding + rightPadding
    height: mainItem.implicitHeight + topPadding + bottomPadding

    mainItem: Item {
        function loadConfig() {
            dialogItem.animationDuration = KWin.readConfig("PopupHideDelay", 1000);
            if (KWin.readConfig("TextOnly", "false") == "true") {
                dialogItem.showGrid = false;
            } else {
                dialogItem.showGrid = true;
            }
        }

        id: dialogItem
        property int screenWidth: 0
        property int screenHeight: 0
        property int currentIndex: 0
        property int previousIndex: 0
        property int animationDuration: 1000
        property bool showGrid: true

        implicitWidth: dialogItem.showGrid ? view.itemWidth * view.columns : Math.ceil(textElement.implicitWidth)
        implicitHeight: dialogItem.showGrid ? view.itemHeight * view.rows + textElement.implicitHeight : textElement.implicitHeight

        Kirigami.Heading {
            id: textElement
            anchors.top: dialogItem.showGrid ? parent.top : undefined
            anchors.left: parent.left
            anchors.right: parent.right
            horizontalAlignment: Text.AlignHCenter
            wrapMode: Text.NoWrap
            elide: Text.ElideRight
            text: Workspace.currentDesktop.name
        }

        Grid {
            id: view
            columns: 1
            rows: 1
            property int itemWidth: dialogItem.screenWidth * Math.min(0.8/columns, 0.1)
            property int itemHeight: Math.min(itemWidth * (dialogItem.screenHeight / dialogItem.screenWidth), dialogItem.screenHeight * Math.min(0.8/rows, 0.1))
            anchors {
                top: textElement.bottom
                left: parent.left
                right: parent.right
                bottom: parent.bottom
            }
            visible: dialogItem.showGrid
            Repeater {
                id: repeater
                model: Workspace.desktops
                Item {
                    width: view.itemWidth
                    height: view.itemHeight
                    KSvg.FrameSvgItem {
                        anchors.fill: parent
                        imagePath: "widgets/pager"
                        prefix: "normal"
                    }
                    KSvg.FrameSvgItem {
                        id: activeElement
                        anchors.fill: parent
                        imagePath: "widgets/pager"
                        prefix: "active"
                        opacity: 0.0
                        Behavior on opacity {
                            NumberAnimation { duration: dialogItem.animationDuration/2 }
                        }
                    }
                    Item {
                        id: arrowsContainer
                        anchors.fill: parent
                        Kirigami.Icon {
                            anchors.fill: parent
                            source: "go-up"
                            visible: false
                        }
                        Kirigami.Icon {
                            anchors.fill: parent
                            source: "go-down"
                            visible: {
                                if (dialogItem.currentIndex <= index) {
                                    // don't show for target desktop
                                    return false;
                                }
                                if (index < dialogItem.previousIndex) {
                                    return false;
                                }
                                if (dialogItem.currentIndex < dialogItem.previousIndex) {
                                    // we only go down if the new desktop is higher
                                    return false;
                                }
                                if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                    // don't show icons in same row as target desktop
                                    return false;
                                }
                                if (dialogItem.previousIndex % view.columns == index % view.columns) {
                                    // show arrows for icons in same column as the previous desktop
                                    return true;
                                }
                                return false;
                            }
                        }
                        Kirigami.Icon {
                            anchors.fill: parent
                            source: "go-up"
                            visible: {
                                if (dialogItem.currentIndex >= index) {
                                    // don't show for target desktop
                                    return false;
                                }
                                if (index > dialogItem.previousIndex) {
                                    return false;
                                }
                                if (dialogItem.currentIndex > dialogItem.previousIndex) {
                                    // we only go down if the new desktop is higher
                                    return false;
                                }
                                if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                    // don't show icons in same row as target desktop
                                    return false;
                                }
                                if (dialogItem.previousIndex % view.columns == index % view.columns) {
                                    // show arrows for icons in same column as the previous desktop
                                    return true;
                                }
                                return false;
                            }
                        }
                        Kirigami.Icon {
                            anchors.fill: parent
                            source: "go-next"
                            visible: {
                                if (dialogItem.currentIndex <= index) {
                                    // we don't show for desktops not on the path
                                    return false;
                                }
                                if (index < dialogItem.previousIndex) {
                                    // we might have to show this icon in case we go up and to the right
                                    if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                        // can only happen in same row
                                        if (index % view.columns >= dialogItem.previousIndex % view.columns) {
                                            // but only for items in the same column or after of the previous desktop
                                            return true;
                                        }
                                    }
                                    return false;
                                }
                                if (dialogItem.currentIndex < dialogItem.previousIndex) {
                                    // we only go right if the new desktop is higher
                                    return false;
                                }
                                if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                    // show icons in same row as target desktop
                                    if (index % view.columns < dialogItem.previousIndex % view.columns) {
                                        // but only for items in the same column or after of the previous desktop
                                        return false;
                                    }
                                    return true;
                                }
                                return false;
                            }
                        }
                        Kirigami.Icon {
                            anchors.fill: parent
                            source: "go-previous"
                            visible: {
                                if (dialogItem.currentIndex >= index) {
                                    // we don't show for desktops not on the path
                                    return false;
                                }
                                if (index > dialogItem.previousIndex) {
                                    // we might have to show this icon in case we go down and to the left
                                    if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                        // can only happen in same row
                                        if (index % view.columns <= dialogItem.previousIndex % view.columns) {
                                            // but only for items in the same column or before the previous desktop
                                            return true;
                                        }
                                    }
                                    return false;
                                }
                                if (dialogItem.currentIndex > dialogItem.previousIndex) {
                                    // we only go left if the new desktop is lower
                                    return false;
                                }
                                if (Math.floor(dialogItem.currentIndex/view.columns) == Math.floor(index/view.columns)) {
                                    // show icons in same row as target desktop
                                    if (index % view.columns > dialogItem.previousIndex % view.columns) {
                                        // but only for items in the same column or before of the previous desktop
                                        return false;
                                    }
                                    return true;
                                }
                                return false;
                            }
                        }
                    }
                    states: [
                        State {
                            name: "NORMAL"
                            when: index != dialogItem.currentIndex
                            PropertyChanges {
                                target: activeElement
                                opacity: 0.0
                            }
                        },
                        State {
                            name: "SELECTED"
                            when: index == dialogItem.currentIndex
                            PropertyChanges {
                                target: activeElement
                                opacity: 1.0
                            }
                        }
                    ]
                    Component.onCompleted: {
                        view.state = (index == dialogItem.currentIndex) ? "SELECTED" : "NORMAL"
                    }
                }
            }
        }

        Timer {
            id: timer
            repeat: false
            interval: dialogItem.animationDuration
            onTriggered: dialog.visible = false
        }

        Connections {
            target: Options
            function onConfigChanged() {
                dialogItem.loadConfig()
            }
        }
        Component.onCompleted: {
            view.columns = Workspace.desktopGridWidth;
            view.rows = Workspace.desktopGridHeight;
            dialogItem.loadConfig();
        }
    }

    function show(previous) {
        if (Workspace.isEffectActive("overview")) {
            return;
        }
        dialogItem.previousIndex = Workspace.desktops.indexOf(previous);
        dialogItem.currentIndex = Workspace.desktops.indexOf(Workspace.currentDesktop);
        // screen geometry might have changed
        var screen = Workspace.clientArea(KWin.FullScreenArea, Workspace.activeScreen, Workspace.currentDesktop);
        dialogItem.screenWidth = screen.width;
        dialogItem.screenHeight = screen.height;
        if (dialogItem.showGrid) {
            // non dependable properties might have changed
            view.columns = Workspace.desktopGridWidth;
            view.rows = Workspace.desktopGridHeight;
        }
        dialog.visible = true;
        // position might have changed
        dialog.x = screen.x + screen.width/2 - dialogItem.width/2;
        dialog.y = screen.y + screen.height/2 - dialogItem.height/2;
        // start the hide timer
        timer.restart();
    }
}
