/*
    SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>

    SPDX-License-Identifier: LGPL-2.0-or-later
*/

pragma ComponentBehavior: Bound

import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as QQC2
import QtQuick.Templates as T
import org.kde.kirigami as Kirigami
import "private" as Private

/*!
   \qmltype GridDelegate
   \inqmlmodule org.kde.kcmutils
   \brief Base delegate for KControlmodules based on Grid views of thumbnails.

   Use the onClicked signal handler for managing the main action when
   the user clicks on the thumbnail.
 */
T.ItemDelegate {
    id: delegate

    /*!
       \brief String for a tooltip for the whole delegate.
     */
    property string toolTip

    /*!
       \brief Optional string for the text to show below the main label.
     */
    property string subtitle

    /*!
       \qmlproperty Item GridDelegate::thumbnail
       \brief The item actually implementing the thumbnail:
       the visualization is up to the implementation.
     */
    property alias thumbnail: thumbnailArea.data

    /*!
       \brief Set it to true when a thumbnail is actually available.

       When false, only an icon will be shown instead of the actual thumbnail
       ("edit-none" if pluginName is "None", otherwise it uses "view-preview").
     */
    property bool thumbnailAvailable: false

    /*!
       \qmlproperty list<Kirigami.Action> GridDelegate::actions
       \brief A list of extra actions for the thumbnails.

       They will be shown as icons on the bottom-right corner
       of the thumbnail on mouse hover.
     */
    property list<Kirigami.Action> actions

    width: GridView.view.cellWidth
    height: GridView.view.cellHeight
    hoverEnabled: !Kirigami.Settings.isMobile

    Accessible.description: {
        if (toolTip.length === 0) {
            return subtitle;
        } else if (subtitle.length === 0) {
            return toolTip;
        }
        return `${subtitle}; ${toolTip}`
    }

    Keys.onEnterPressed: event => thumbnail.trigger()
    Keys.onMenuPressed: event => thumbnail.trigger()
    Keys.onSpacePressed: event => thumbnail.trigger()

    Kirigami.ShadowedRectangle {
        id: thumbnail
        anchors {
           centerIn: parent
           verticalCenterOffset: Math.ceil(-labelLayout.height / 2)
        }
        width: Math.min(delegate.GridView.view.implicitCellWidth, delegate.width - Kirigami.Units.gridUnit)
        height: Math.min(delegate.GridView.view.implicitCellHeight - Kirigami.Units.gridUnit * 3,
                         delegate.height - Kirigami.Units.gridUnit)
        radius: Kirigami.Units.cornerRadius
        Kirigami.Theme.inherit: false
        Kirigami.Theme.colorSet: Kirigami.Theme.View

        shadow.xOffset: 0
        shadow.yOffset: 2
        shadow.size: 10
        shadow.color: Qt.rgba(0, 0, 0, 0.3)

        color: {
            if (delegate.GridView.isCurrentItem) {
                if (delegate.enabled && delegate.GridView.view.neutralHighlight) {
                    return Kirigami.Theme.neutralTextColor;
                }
                return Kirigami.Theme.highlightColor;
            }
            if (delegate.enabled && delegate.hovered) {
                // Match appearance of hovered list items
                return Qt.alpha(Kirigami.Theme.highlightColor, 0.5);
            }
            return Kirigami.Theme.backgroundColor;
        }

        // The menu is only used for keyboard navigation, so no need to always load
        // it. This speeds up the compilation of GridDelegate.
        property Private.GridDelegateMenu menu

        function trigger() {
            if (!menu) {
                const component = Qt.createComponent("private/GridDelegateMenu.qml");
                menu = component.createObject(delegate);
                component.destroy();
            }

            menu.trigger();
        }

        Rectangle {
            id: thumbnailArea

            radius: Math.round(Kirigami.Units.cornerRadius / 2)
            anchors {
                fill: parent
                margins: Kirigami.Units.smallSpacing
            }

            color: Kirigami.Theme.backgroundColor

            // "None/There's nothing here" indicator
            Kirigami.Icon {
                visible: !delegate.thumbnailAvailable
                anchors.centerIn: parent
                width: Kirigami.Units.iconSizes.large
                height: Kirigami.Units.iconSizes.large
                source: typeof pluginName === "string" && pluginName === "None" ? "edit-none" : "view-preview"
            }

            RowLayout {
                anchors {
                    right: parent.right
                    rightMargin: Kirigami.Units.smallSpacing
                    bottom: parent.bottom
                    bottomMargin: Kirigami.Units.smallSpacing
                }
                spacing: Kirigami.Units.smallSpacing

                // Always show above thumbnail content
                z: 9999

                visible: delegate.actions.length > 0 && (Kirigami.Settings.isMobile || delegate.hovered || delegate.GridView.isCurrentItem)

                Repeater {
                    model: delegate.actions
                    delegate: QQC2.Button {
                        required property Kirigami.Action modelData

                        icon.name: modelData.icon.name
                        text: modelData.text || modelData.tooltip
                        display: QQC2.AbstractButton.IconOnly

                        enabled: modelData.enabled
                        visible: modelData.visible

                        activeFocusOnTab: false

                        onClicked: modelData.trigger()

                        QQC2.ToolTip.visible: (Kirigami.Settings.tabletMode ? pressed : hovered) && (QQC2.ToolTip.text !== "")
                        QQC2.ToolTip.delay: Kirigami.Settings.tabletMode ? Qt.styleHints.mousePressAndHoldInterval : Kirigami.Units.toolTipDelay
                        QQC2.ToolTip.text: text
                    }
                }
            }
        }
    }

    ColumnLayout {
        id: labelLayout

        spacing: 0
        height: Kirigami.Units.gridUnit * 2
        anchors {
            left: thumbnail.left
            right: thumbnail.right
            top: thumbnail.bottom
            topMargin: Kirigami.Units.largeSpacing
        }

        QQC2.Label {
            id: title

            Layout.fillWidth: true
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignTop
            text: delegate.text
            color: enabled ? Kirigami.Theme.textColor : Kirigami.Theme.disabledTextColor
            maximumLineCount: 1
            elide: Text.ElideRight
            font.bold: delegate.GridView.isCurrentItem
            textFormat: Text.PlainText
        }
        QQC2.Label {
            id: caption

            Layout.fillWidth: true
            horizontalAlignment: Text.AlignHCenter
            visible: delegate.subtitle.length > 0
            opacity: 0.6
            text: delegate.subtitle
            font.pointSize: Kirigami.Theme.smallFont.pointSize
            font.bold: delegate.GridView.isCurrentItem
            maximumLineCount: 1
            elide: Text.ElideRight
            textFormat: Text.PlainText
        }

        Rectangle {
            Layout.preferredHeight: 1
            Layout.preferredWidth: Math.max(title.paintedWidth, caption.paintedWidth)
            Layout.maximumWidth: labelLayout.width // Otherwise labels can overflow
            Layout.alignment: Qt.AlignHCenter

            color: Kirigami.Theme.highlightColor

            opacity: delegate.visualFocus ? 1 : 0
        }

        Item { Layout.fillWidth: true; Layout.fillHeight: true; }
    }

    QQC2.ToolTip.visible: (Kirigami.Settings.tabletMode ? pressed : hovered) && (QQC2.ToolTip.text !== "")
    QQC2.ToolTip.delay: Kirigami.Settings.tabletMode ? Qt.styleHints.mousePressAndHoldInterval : Kirigami.Units.toolTipDelay
    QQC2.ToolTip.text: {
        const parts = [];
        if (delegate.toolTip.length > 0) {
            parts.push(delegate.toolTip);
        }
        if (title.truncated) {
            parts.push(title.text);
        }
        if (caption.truncated) {
            parts.push(caption.text);
        }
        return parts.join("\n");
    }
}
