/**
 * SPDX-FileCopyrightText: 2023 Bart De Vries <bart@mogwai.be>
 *
 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
 */

import QtQuick
import QtQuick.Controls as Controls
import QtQuick.Layouts
import QtQml.Models

import org.kde.kirigami as Kirigami
import org.kde.kmediasession

import org.kde.kasts
import org.kde.kasts.settings

import ".."

FocusScope {
    id: desktopPlayerControls
    implicitHeight: playerControlToolBar.implicitHeight + Kirigami.Units.largeSpacing * 2

    property alias chapterModel: chapterModel
    /*
     * Emmited when User uses the Item as a handle to resize the layout.
     * y: difference to previous position
     * offset: cursor offset (y coordinate relative to this Item, where dragging
     * begun)
     */
    signal handlePositionChanged(int y, int offset)

    Rectangle {
        id: toolbarBackground
        anchors.fill: parent

        opacity: 0.7

        //set background color
        Kirigami.Theme.inherit: false
        Kirigami.Theme.colorSet: Kirigami.Theme.Header
        color: Kirigami.Theme.backgroundColor

        MouseArea {
          anchors.fill: parent
          property int dragStartOffset: 0

          cursorShape: Qt.SizeVerCursor

          onPressed: (mouse) => {
            dragStartOffset = mouse.y
          }

          onPositionChanged: (mouse) => {
            desktopPlayerControls.handlePositionChanged(mouse.y, dragStartOffset)
          }

          drag.axis: Drag.YAxis
          drag.threshold: 1
        }
    }

    RowLayout {
        id: playerControlToolBar

        anchors.fill: parent
        anchors.topMargin: Kirigami.Units.largeSpacing
        anchors.bottomMargin: Kirigami.Units.largeSpacing
        anchors.rightMargin: Kirigami.Units.smallSpacing
        anchors.leftMargin: Kirigami.Units.smallSpacing

        property int audioSliderNiceMinimumWidth: 300
        property int audioSliderAbsoluteMinimumWidth: 200

        // size of volumeButton serves as size of extra buttons too
        // this is chosen because the volumeButton is always visible
        property bool tooNarrowExtra: playerControlToolBar.width - (audioButtons.width + 4 * volumeButton.width + (chapterAction.visible ? chapterTextMetric.width : 0) + extraButtonsTextMetric.width) < audioSliderNiceMinimumWidth + 40

        property bool tooNarrowChapter: playerControlToolBar.width - (audioButtons.width + 4 * volumeButton.width + (chapterAction.visible ? chapterTextMetric.width : 0)) < audioSliderNiceMinimumWidth +  20

        property bool tooNarrowOverflow: playerControlToolBar.width - (audioButtons.width + 4 * volumeButton.width) < audioSliderNiceMinimumWidth

        property bool tooNarrowAudioLabels: playerControlToolBar.width - (audioButtons.width + 2 * volumeButton.width) < audioSliderAbsoluteMinimumWidth

        clip: true

        Loader {
            Layout.fillHeight: true
            Layout.preferredWidth: height
            active: headerBar.handlePosition === 0
            visible: active
            sourceComponent: imageComponent
        }

        Component {
            id: imageComponent
            ImageWithFallback {
                id: frontImage
                imageSource: headerMetaData.image
                absoluteRadius: Kirigami.Units.smallSpacing
                visible: headerBar.handlePosition === 0
                MouseArea {
                    anchors.fill: parent
                    cursorShape: Qt.PointingHandCursor
                    onClicked: {
                        headerBar.openFullScreenImage();
                    }
                }
            }
        }

        RowLayout {
            id: audioButtons
            Controls.ToolButton {
                icon.name: "media-seek-backward"
                onClicked: AudioManager.skipBackward()
                enabled: AudioManager.canSkipBackward

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18n("Seek backward")
            }
            Controls.ToolButton {
                id: playButton
                icon.name: AudioManager.playbackState === KMediaSession.PlayingState ? "media-playback-pause" : "media-playback-start"
                onClicked: AudioManager.playbackState === KMediaSession.PlayingState ? AudioManager.pause() : AudioManager.play()
                enabled: AudioManager.canPlay

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: AudioManager.playbackState === KMediaSession.PlayingState ? i18n("Pause") : i18n("Play")
            }
            Controls.ToolButton {
                icon.name: "media-seek-forward"
                onClicked: AudioManager.skipForward()
                enabled: AudioManager.canSkipForward

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18n("Seek forward")
            }
            Controls.ToolButton {
                icon.name: "media-skip-forward"
                onClicked: AudioManager.next()
                enabled: AudioManager.canGoNext

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18n("Skip forward")
            }
            Controls.ToolButton {
                id: playbackRateButton
                text: AudioManager.playbackRate.toFixed(2) + "x"
                checkable: true
                checked: playbackRateMenu.visible
                onClicked: {
                    if (playbackRateMenu.visible) {
                        playbackRateMenu.dismiss();
                    } else {
                        playbackRateMenu.popup(playbackRateButton, 0, playbackRateButton.height);
                    }
                }
                padding: 0
                implicitWidth: playButton.width * 1.5
                implicitHeight: playButton.height

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18n("Playback rate:") + " " + AudioManager.playbackRate.toFixed(2) + "x"
            }
        }

        Controls.Label {
            id: currentPositionLabel
            text: AudioManager.formattedPosition
            visible: !playerControlToolBar.tooNarrowAudioLabels
            Layout.alignment: Qt.AlignVCenter
        }

        ChapterSlider {
            id: durationSlider
            model: chapterModel
            enabled: AudioManager.entry && AudioManager.PlaybackState != AudioManager.StoppedState && AudioManager.canPlay
            Layout.fillWidth: true
            Layout.alignment: Qt.AlignVCenter
        }

        Item {
            id: durationLabel
            visible: !playerControlToolBar.tooNarrowAudioLabels
            Layout.preferredHeight: endLabel.implicitHeight
            Layout.preferredWidth: endLabel.implicitWidth
            Layout.rightMargin: Kirigami.Units.largeSpacing
            Layout.alignment: Qt.AlignVCenter

            Controls.Label {
                id: endLabel
                anchors.right: parent.right
                anchors.verticalCenter: parent.verticalCenter
                text: (SettingsManager.toggleRemainingTime) ?
                        "-" + AudioManager.formattedLeftDuration
                        : AudioManager.formattedDuration
            }

            MouseArea {
                anchors.fill: parent
                hoverEnabled: true
                onClicked: {
                    SettingsManager.toggleRemainingTime = !SettingsManager.toggleRemainingTime;
                    SettingsManager.save();
                }
            }
        }

        RowLayout {
            id: extraButtons
            visible: !playerControlToolBar.tooNarrowOverflow
            Controls.ToolButton {
                id: chapterButton
                action: chapterAction
                display: playerControlToolBar.tooNarrowChapter ? Controls.AbstractButton.IconOnly : Controls.AbstractButton.TextBesideIcon
                visible: chapterAction.visible && !playerControlToolBar.tooNarrowOverflow

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18nc("@action:button", "Show chapter list")
            }

            Controls.ToolButton {
                id: infoButton
                action: infoAction
                display: playerControlToolBar.tooNarrowExtra ? Controls.AbstractButton.IconOnly : Controls.AbstractButton.TextBesideIcon
                visible: infoAction.visible && !playerControlToolBar.tooNarrowOverflow

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18nc("@action:button", "Show episode info")
            }

            Controls.ToolButton {
                id: sleepButton
                action: sleepAction
                display: playerControlToolBar.tooNarrowExtra ? Controls.AbstractButton.IconOnly : Controls.AbstractButton.TextBesideIcon
                visible:  !playerControlToolBar.tooNarrowOverflow

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18nc("@action:button", "Open sleep timer settings")
            }
        }

        RowLayout {
            id: volumeControls
            Controls.ToolButton {
                id: volumeButton
                icon.name: AudioManager.muted ? "player-volume-muted" : "player-volume"
                enabled: AudioManager.PlaybackState != AudioManager.StoppedState && AudioManager.canPlay
                checked: volumePopup.visible

                Controls.ToolTip.visible: hovered
                Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                Controls.ToolTip.text: i18nc("@action:button", "Open volume settings")

                onClicked: {
                    if (volumePopup.visible) {
                        volumePopup.close();
                    } else {
                        volumePopup.open();
                    }
                }

                Controls.Popup {
                    id: volumePopup
                    x: -padding
                    y: volumeButton.height

                    focus: true
                    padding: Kirigami.Units.smallSpacing
                    contentWidth: volumeButtonVertical.implicitWidth

                    contentItem: ColumnLayout {
                        VolumeSlider {
                            id: volumeSlider
                        }

                        Controls.ToolButton {
                            id: volumeButtonVertical
                            enabled: AudioManager.PlaybackState != AudioManager.StoppedState && AudioManager.canPlay
                            icon.name: AudioManager.muted ? "player-volume-muted" : "player-volume"
                            onClicked: AudioManager.muted = !AudioManager.muted

                            Controls.ToolTip.visible: hovered
                            Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
                            Controls.ToolTip.text: i18nc("@action:button", "Toggle mute")

                        }
                    }
                }
            }
        }

        Controls.ToolButton {
            id: overflowButton
            icon.name: "overflow-menu"
            display: Controls.AbstractButton.IconOnly
            visible: playerControlToolBar.tooNarrowOverflow
            checked: overflowMenu.visible

            Controls.ToolTip.visible: hovered
            Controls.ToolTip.delay: Kirigami.Units.toolTipDelay
            Controls.ToolTip.text: i18nc("@action:button", "Show more")

            onClicked: {
                if (overflowMenu.visible) {
                    overflowMenu.dismiss();
                } else {
                    overflowMenu.popup(0, overflowButton.height)
                }
            }

            Controls.Menu {
                id: overflowMenu
                contentData: extraActions
                onVisibleChanged: {
                    if (visible) {
                        for (var i in contentData) {
                            overflowMenu.contentData[i].visible = overflowMenu.contentData[i].action.visible;
                            overflowMenu.contentData[i].height =
                            (overflowMenu.contentData[i].action.visible) ? overflowMenu.contentData[i].implicitHeight : 0 // workaround for qqc2-breeze-style
                        }
                    }
                }
            }
        }
    }

    // Actions which will be used to create buttons on toolbar or in overflow menu
    Kirigami.Action {
        id: chapterAction
        property bool visible: AudioManager.entry && chapterList.count !== 0
        text: i18nc("@action:button", "Chapters")
        icon.name: "view-media-playlist"
        onTriggered: chapterOverlay.open();
    }

    Kirigami.Action {
        id: infoAction
        property bool visible: AudioManager.entry
        text: i18nc("@action:button", "Show Info")
        icon.name: "documentinfo"
        onTriggered: entryDetailsOverlay.open();
    }

    Kirigami.Action {
        id: sleepAction
        checkable: true
        checked: AudioManager.remainingSleepTime > 0
        property bool visible: true
        text: i18nc("@action:button", "Sleep Timer")
        icon.name: "clock"
        onTriggered: {
            toggle(); // only set the on/off state based on sleep timer state
            sleepTimerDialog.open();
        }
    }

    property var extraActions: [ chapterAction,
                                 infoAction,
                                 sleepAction ]

    TextMetrics {
        id: chapterTextMetric
        text: chapterAction.text
    }

    TextMetrics {
        id: extraButtonsTextMetric
        text: infoAction.text + sleepAction.text
    }

    ChapterModel {
        id: chapterModel
        entry: AudioManager.entry ? AudioManager.entry : null
        duration: AudioManager.duration
    }

    Kirigami.Dialog {
        id: chapterOverlay

        showCloseButton: false

        title: i18n("Chapters")

        ListView {
            id: chapterList

            currentIndex: -1

            implicitWidth: Kirigami.Units.gridUnit * 30
            implicitHeight: Kirigami.Units.gridUnit * 25

            model: chapterModel
            delegate: ChapterListDelegate {
                id: chapterDelegate
                width: chapterList.width
                entry: AudioManager.entry ? AudioManager.entry : null
                overlay: chapterOverlay
            }
        }
    }

    Kirigami.Dialog {
        id: entryDetailsOverlay
        preferredWidth: Kirigami.Units.gridUnit * 30

        showCloseButton: false

        title: AudioManager.entry ? AudioManager.entry.title : i18n("No Track Title")
        padding: Kirigami.Units.largeSpacing

        Controls.Label {
            id: text
            text: AudioManager.entry ? AudioManager.entry.adjustedContent(width, font.pixelSize) : i18n("No track loaded")
            verticalAlignment: Text.AlignTop
            baseUrl: AudioManager.entry ? AudioManager.entry.baseUrl : ""
            textFormat: Text.RichText
            wrapMode: Text.WordWrap
            onLinkHovered: {
                cursorShape: Qt.PointingHandCursor;
            }
            onLinkActivated: (link) => {
                if (link.split("://")[0] === "timestamp") {
                    if (AudioManager.entry && AudioManager.entry.enclosure) {
                        AudioManager.seek(link.split("://")[1]);
                    }
                } else {
                    Qt.openUrlExternally(link);
                }
            }
        }
    }

    PlaybackRateMenu {
        id: playbackRateMenu
        parentButton: playbackRateButton
    }
}
