/*
 *  SPDX-FileCopyrightText: 2014-2015 Harald Sitter <sitter@kde.org>
 *  SPDX-FileCopyrightText: 2019 Sefa Eyeoglu <contact@scrumplex.net>
 *  SPDX-FileCopyrightText: 2021 Devin Lin <espidev@gmail.com>
 *
 *  SPDX-License-Identifier: GPL-2.0-or-later
 */

import QtQuick
import QtQuick.Controls as Controls
import QtQuick.Layouts

import org.kde.kirigami as Kirigami
import org.kde.ksvg as KSvg
import org.kde.kquickcontrolsaddons
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.plasma.extras as PlasmaExtras
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.volume

import "icon.js" as Icon

// adapted from https://invent.kde.org/plasma/plasma-pa/-/blob/master/applet/contents/ui/ListItemBase.qml
Controls.AbstractButton {
    id: baseItem

    hoverEnabled: true

    property string label
    property alias listIcon: clientIcon.source
    property string type // sink, source, source-output

    property bool onlyOne: false

    // Whether this item is selected
    readonly property bool supportsSelection: (baseItem.type == "sink" || baseItem.type == "source")
    readonly property bool selected: supportsSelection && (model.PulseObject.hasOwnProperty("default") ? model.PulseObject.default : false)

    onClicked: {
        // Set as the default audio device
        model.PulseObject.default = true
    }

    topPadding: Kirigami.Units.mediumSpacing
    bottomPadding: Kirigami.Units.mediumSpacing
    leftPadding: Kirigami.Units.mediumSpacing
    rightPadding: Kirigami.Units.mediumSpacing

    background: Rectangle {
        radius: Kirigami.Units.cornerRadius
        color: "transparent"

        MobileShell.MotionStateLayer {
            anchors.fill: parent
            radius: parent.radius
            hovered: baseItem.hovered
            pressed: baseItem.down
            active: baseItem.selected
        }
    }

    contentItem: RowLayout {
        id: row
        spacing: Kirigami.Units.smallSpacing

        // application icon
        Kirigami.Icon {
            id: clientIcon
            Layout.alignment: Qt.AlignVCenter
            Layout.rightMargin: Kirigami.Units.smallSpacing
            Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
            Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
            visible: type === "sink-input" || type === "source-output"
            source: "unknown"
            onSourceChanged: {
                if (!valid && source != "unknown") {
                    source = "unknown";
                }
            }
        }

        RowLayout {
            spacing: 0
            Layout.maximumWidth: Infinity // Ignore maximum width of children
            visible: (baseItem.type === "sink" || baseItem.type === "source") && !baseItem.onlyOne

            PlasmaComponents.RadioButton {
                id: defaultButton
                Accessible.ignored: true // read out from delegate
                activeFocusOnTab: false // toggle from delegate
                checked: model.PulseObject?.default ?? false
                onToggled: {
                    if (checked) {
                        baseItem.click();
                    }
                }
            }
        }

        ColumnLayout {
            Layout.alignment: Qt.AlignVCenter
            Layout.fillWidth: true
            spacing: Kirigami.Units.smallSpacing

            RowLayout {
                Layout.fillWidth: true
                spacing: Kirigami.Units.smallSpacing
                Layout.alignment: Qt.AlignBottom

                PlasmaComponents.Label {
                    id: mainLabel
                    text: baseItem.label
                    Layout.alignment: Qt.AlignBottom
                    Layout.fillWidth: true
                    elide: Text.ElideRight
                }

                PlasmaComponents.ToolButton {
                    id: viewButton
                    Layout.alignment: Qt.AlignBottom
                    Layout.bottomMargin: -Kirigami.Units.smallSpacing
                    icon.name: "view-more-symbolic"
                    checkable: true
                    checked: contextMenu.visible && contextMenu.visualParent === this
                    visible: contextMenu.hasContent
                    onClicked: {
                        contextMenu.visualParent = this;
                        contextMenu.openRelative();
                    }
                    PlasmaComponents.ToolTip {
                        text: i18n("Show additional options for %1", baseItem.label)
                    }

                    ListItemMenu {
                        id: contextMenu
                        pulseObject: model.PulseObject
                        cardModel: paCardModel
                        itemType: {
                            switch (baseItem.type) {
                            case "sink":
                                return ListItemMenu.Sink;
                            case "sink-input":
                                return ListItemMenu.SinkInput;
                            case "source":
                                return ListItemMenu.Source;
                            case "source-output":
                                return ListItemMenu.SourceOutput;
                            }
                        }
                        sourceModel: {
                            if (baseItem.type.includes("sink")) {
                                return sinkView.model;
                            } else if (baseItem.type.includes("source")) {
                                return sourceView.model;
                            }
                        }
                    }
                }
            }

            RowLayout {
                Layout.fillWidth: true
                spacing: Kirigami.Units.smallSpacing

                // this slider was effectively copied from the source (linked at the top of the file)
                VolumeSlider {
                    id: slider

                    Layout.fillWidth: true
                    from: PulseAudio.MinimalVolume
                    to: model.Volume >= PulseAudio.NormalVolume * 1.01 ? PulseAudio.MaximalVolume : PulseAudio.NormalVolume
                    stepSize: PulseAudio.NormalVolume / 100.0
                    property real myStepSize: PulseAudio.NormalVolume / 100.0
                    visible: model.HasVolume !== false // Devices always have volume but Streams don't necessarily
                    enabled: model.VolumeWritable
                    muted: model.Muted
                    volumeObject: model.PulseObject
                    activeFocusOnTab: false // access from delegate

                    value: to, model.Volume
                    onMoved: {
                        model.Volume = value;
                        model.Muted = value === 0;
                    }
                    onPressedChanged: {
                        if (!pressed) {
                            // Make sure to sync the volume once the button was
                            // released.
                            // Otherwise it might be that the slider is at v10
                            // whereas PA rejected the volume change and is
                            // still at v15 (e.g.).
                            value = Qt.binding(() => model.Volume);
                        }
                    }

                    function updateVolume() {
                        if (model.Volume > PulseAudio.NormalVolume) {
                            model.Volume = PulseAudio.NormalVolume;
                        }
                    }

                    SequentialAnimation {
                        id: seqAnimation
                        MobileShell.MotionNumberAnimation {
                            id: toAnimation
                            target: slider
                            property: "to"
                            type: MobileShell.Motion.EffectsFast
                        }
                        ScriptAction {
                            script: slider.updateVolume()
                        }
                    }
                }
                PlasmaComponents.Label {
                    id: percentText
                    readonly property real value: model.PulseObject.volume > slider.to ? model.PulseObject.volume : slider.value
                    readonly property real displayValue: Math.round(value / PulseAudio.NormalVolume * 100.0)
                    Layout.alignment: Qt.AlignHCenter
                    Layout.minimumWidth: percentMetrics.advanceWidth
                    horizontalAlignment: Qt.AlignRight
                    text: i18nc("volume percentage", "%1%", displayValue)
                    color: {
                        if (displayValue <= 100) {
                            return Kirigami.Theme.textColor
                        } else if (displayValue > 100 && displayValue <= 125) {
                            return Kirigami.Theme.neutralTextColor
                        } else {
                            return Kirigami.Theme.negativeTextColor
                        }
                    }
                }

                TextMetrics {
                    id: percentMetrics
                    font: percentText.font
                    text: i18nc("only used for sizing, should be widest possible string", "100%")
                }
            }
        }
    }
}
