// The wallpaper grid.
//
// A thumbnail grid rather than a file path field: choosing a background is the
// one setting where the value IS the picture, and typing a path to something
// you cannot see is the worst possible version of it.
//
// Images are loaded asynchronously and at a fraction of their real size --
// several of the candidates here are 8-12 MB, and decoding them at full
// resolution to draw a 150px tile would cost more memory than the rest of the
// shell put together.

import QtQuick
import QtQuick.Effects
import qs.config
import qs.services

Item {
    id: root

    implicitHeight: grid.implicitHeight

    // Sixty tiles is two screens of wallpaper on a page that also holds
    // typography, window geometry and effects -- everything below it becomes
    // unreachable without a long scroll past pictures. Two rows by default,
    // all of them on request.
    property bool expanded: false
    readonly property int collapsedRows: 2

    readonly property var shown: root.expanded
        ? Wallpaper.available
        : Wallpaper.available.slice(0, root.columns * root.collapsedRows)

    readonly property int hidden: Wallpaper.available.length - root.shown.length

    readonly property int columns: Math.max(2, Math.floor(width / 190))
    readonly property real cellWidth: columns > 0 ? (width - (columns - 1) * 10) / columns : 160

    Grid {
        id: grid

        width: parent.width
        columns: root.columns
        spacing: 10

        Repeater {
            model: root.shown

            Rectangle {
                id: tile

                required property var modelData

                readonly property bool current: Wallpaper.active === tile.modelData

                width: root.cellWidth
                height: Math.round(root.cellWidth * 9 / 16)
                radius: Theme.cardRadius
                color: Theme.alpha(Theme.bgDark, 0.6)
                clip: true
                border.width: 0

                Image {
                    id: thumbnail

                    anchors.fill: parent
                    source: "file://" + tile.modelData
                    fillMode: Image.PreserveAspectCrop
                    asynchronous: true
                    cache: false
                    // Decode to roughly the size actually drawn. Without this a
                    // grid of 12MB photographs decodes at full resolution.
                    sourceSize.width: 400
                    sourceSize.height: 240

                    // Several of these are 8-12MB originals, so a tile can sit
                    // empty for a second or two. Fading in on ready makes that
                    // read as loading rather than as a broken image, and the
                    // fade runs once per tile rather than continuously.
                    opacity: status === Image.Ready ? 1 : 0
                    Behavior on opacity {
                        NumberAnimation { duration: Theme.durNormal; easing.type: Easing.OutQuad }
                    }
                }

                Text {
                    anchors.centerIn: parent
                    visible: thumbnail.status === Image.Loading
                    text: "Loading…"
                    color: Theme.fgMuted
                    font.family: Theme.fontFamily
                    font.pixelSize: Theme.fontSizeSmall
                }

                Text {
                    anchors.centerIn: parent
                    width: parent.width - 20
                    horizontalAlignment: Text.AlignHCenter
                    wrapMode: Text.WordWrap
                    visible: thumbnail.status === Image.Error
                    text: "Could not read this image"
                    color: Theme.fgMuted
                    font.family: Theme.fontFamily
                    font.pixelSize: Theme.fontSizeSmall
                }

                // The prism marks the active wallpaper, the same way it marks
                // the focused window and the selected sidebar entry.
                Rectangle {
                    anchors.fill: parent
                    radius: parent.radius
                    visible: tile.current
                    color: "transparent"
                    border.width: 2
                    border.color: Theme.accent
                }

                Rectangle {
                    anchors.left: parent.left
                    anchors.right: parent.right
                    anchors.bottom: parent.bottom
                    height: 26
                    visible: tile.current || hover.hovered
                    border.width: 0

                    gradient: Gradient {
                        GradientStop { position: 0.0; color: Theme.alpha(Theme.bgDark, 0.0) }
                        GradientStop { position: 1.0; color: Theme.alpha(Theme.bgDark, 0.88) }
                    }

                    Text {
                        anchors.left: parent.left
                        anchors.right: parent.right
                        anchors.bottom: parent.bottom
                        anchors.margins: 7
                        text: tile.current ? "Current wallpaper" : Wallpaper.titleFor(tile.modelData)
                        color: tile.current ? Theme.accent : Theme.fg
                        font.family: Theme.fontFamily
                        font.pixelSize: Theme.fontSizeSmall
                        font.weight: tile.current ? Font.DemiBold : Font.Normal
                        elide: Text.ElideRight
                    }
                }

                HoverHandler { id: hover }

                TapHandler {
                    onTapped: Wallpaper.set(tile.modelData)
                }
            }
        }
    }

    Text {
        anchors.centerIn: parent
        visible: Wallpaper.available.length === 0 && !Wallpaper.scanning
        width: parent.width - 40
        horizontalAlignment: Text.AlignHCenter
        wrapMode: Text.WordWrap
        text: "No images found. Panama looks in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
        color: Theme.fgMuted
        font.family: Theme.fontFamily
        font.pixelSize: Theme.fontSizeSmall
    }
}
