import QtQuick
import Quickshell.Services.Pipewire
import qs.Common
import qs.Services
import qs.Widgets

Item {
    id: root
    visible: dropdownType !== 0

    LayoutMirroring.enabled: I18n.isRtl
    LayoutMirroring.childrenInherit: true

    property int dropdownType: 0
    property var activePlayer: null
    property var allPlayers: []
    // Chromium keeps dead MPRIS services registered w/empty metadata; avoid listing them
    readonly property var selectablePlayers: (allPlayers || []).filter(p => p && !MprisController.isIdle(p))
    property point anchorPos: Qt.point(0, 0)
    property bool isRightEdge: false
    property var targetWindow: null

    property bool __isChromeBrowser: {
        if (!activePlayer?.identity)
            return false;
        const id = activePlayer.identity.toLowerCase();
        return id.includes("chrome") || id.includes("chromium");
    }
    property bool usePlayerVolume: activePlayer && activePlayer.volumeSupported && !__isChromeBrowser
    property real currentVolume: usePlayerVolume ? activePlayer.volume : (AudioService.sink?.audio?.volume ?? 0)
    property bool volumeAvailable: !!((activePlayer && activePlayer.volumeSupported && !__isChromeBrowser) || (AudioService.sink && AudioService.sink.audio))
    property var availableDevices: {
        const hidden = SessionData.hiddenOutputDeviceNames ?? [];
        return Pipewire.nodes.values.filter(node => {
            if (!node.audio || !node.isSink || node.isStream)
                return false;
            return !hidden.includes(node.name);
        });
    }

    signal closeRequested
    signal deviceSelected(var device)
    signal playerSelected(var player)
    signal volumeChanged(real volume)
    signal panelEntered
    signal panelExited

    property int __panelHoverCount: 0

    readonly property bool overlayBlurActive: dropdownBlur.active

    onDropdownTypeChanged: {
        if (dropdownType === 0) {
            __panelHoverCount = 0;
        }
    }

    function panelAreaEntered() {
        __panelHoverCount++;
        panelEntered();
    }

    function panelAreaExited() {
        __panelHoverCount = Math.max(0, __panelHoverCount - 1);
        if (__panelHoverCount === 0)
            panelExited();
    }

    property real _wheelAccum: 0

    function volumeWheel(wheelEvent) {
        if (!volumeAvailable)
            return;
        wheelEvent.accepted = true;
        _wheelAccum += wheelEvent.angleDelta.y;
        const notches = _wheelAccum > 0 ? Math.floor(_wheelAccum / 120) : Math.ceil(_wheelAccum / 120);
        if (notches === 0)
            return;
        _wheelAccum -= notches * 120;
        SessionData.suppressOSDTemporarily();
        const next = currentVolume + notches * AudioService.wheelVolumeStep / 100;
        root.volumeChanged(Math.max(0, Math.min(1, next)));
    }

    readonly property Item __activePanel: {
        switch (dropdownType) {
        case 1:
            return volumePanel;
        case 2:
            return audioDevicesPanel;
        case 3:
            return playersPanel;
        default:
            return null;
        }
    }

    WindowBlur {
        id: dropdownBlur
        targetWindow: root.targetWindow
        readonly property bool active: root.__activePanel !== null && root.__activePanel.visible && root.__activePanel.opacity > 0
        blurEnabled: active && Theme.connectedSurfaceBlurEnabled
        readonly property real s: root.__activePanel ? Math.min(1, root.__activePanel.scale) : 1
        blurX: root.__activePanel ? root.__activePanel.x + root.__activePanel.width * (1 - s) * 0.5 : 0
        blurY: root.__activePanel ? root.__activePanel.y + root.__activePanel.height * (1 - s) * 0.5 : 0
        blurWidth: active ? root.__activePanel.width * s : 0
        blurHeight: active ? root.__activePanel.height * s : 0
        blurRadius: Theme.cornerRadius * 2
    }

    Rectangle {
        id: volumePanel
        visible: dropdownType === 1 && volumeAvailable
        width: 60
        height: 180
        x: isRightEdge ? anchorPos.x : anchorPos.x - width
        y: anchorPos.y - height / 2
        radius: Theme.cornerRadius * 2
        color: Theme.floatingSurface
        border.color: Theme.outlineStrong
        border.width: 1

        opacity: Theme.isDirectionalEffect ? 1 : (dropdownType === 1 ? 1 : 0)
        scale: Theme.isDirectionalEffect ? 1 : (dropdownType === 1 ? 1 : Theme.effectScaleCollapsed)
        transformOrigin: isRightEdge ? Item.Left : Item.Right

        Behavior on opacity {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                easing.type: Easing.BezierSpline
                duration: Math.round(Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 1) * Theme.variantOpacityDurationScale)
                easing.bezierCurve: dropdownType === 1 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        Behavior on scale {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 1)
                easing.type: Easing.BezierSpline
                easing.bezierCurve: dropdownType === 1 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        ElevationShadow {
            id: volumeShadowLayer
            anchors.fill: parent
            z: -1
            level: Theme.elevationLevel2
            fallbackOffset: 4
            targetRadius: volumePanel.radius
            targetColor: volumePanel.color
            borderColor: volumePanel.border.color
            borderWidth: volumePanel.border.width
            shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
            shadowEnabled: Theme.elevationEnabled
        }

        MouseArea {
            anchors.fill: parent
            anchors.margins: -12
            hoverEnabled: true
            onEntered: panelAreaEntered()
            onExited: panelAreaExited()
            onWheel: wheelEvent => root.volumeWheel(wheelEvent)
        }

        Item {
            anchors.fill: parent
            anchors.margins: Theme.spacingS

            Item {
                id: volumeSlider
                width: parent.width * 0.5
                height: parent.height - Theme.spacingXL * 2
                anchors.top: parent.top
                anchors.topMargin: Theme.spacingS
                anchors.horizontalCenter: parent.horizontalCenter

                Rectangle {
                    width: parent.width
                    height: parent.height
                    anchors.centerIn: parent
                    color: Theme.withAlpha(Theme.outline, Theme.popupTransparency)
                    radius: Theme.cornerRadius
                }

                Rectangle {
                    readonly property real ratio: volumeAvailable ? Math.min(1.0, currentVolume) : 0
                    readonly property real thumbHeight: 4
                    width: parent.width
                    height: Math.max(0, ratio * (parent.height - thumbHeight) - 3)
                    anchors.bottom: parent.bottom
                    anchors.horizontalCenter: parent.horizontalCenter
                    color: Theme.primary
                    radius: Theme.cornerRadius
                    topLeftRadius: 0
                    topRightRadius: 0
                }

                Rectangle {
                    width: parent.width + 8
                    height: 4
                    radius: Theme.cornerRadius
                    y: {
                        const ratio = volumeAvailable ? Math.min(1.0, currentVolume) : 0;
                        const travel = parent.height - height;
                        return Math.max(0, Math.min(travel, travel * (1 - ratio)));
                    }
                    anchors.horizontalCenter: parent.horizontalCenter
                    color: Theme.primary
                    border.width: 0
                }

                MouseArea {
                    anchors.fill: parent
                    anchors.margins: -12
                    enabled: volumeAvailable
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    preventStealing: true

                    onEntered: panelAreaEntered()
                    onExited: panelAreaExited()
                    onWheel: wheelEvent => root.volumeWheel(wheelEvent)
                    onPressed: mouse => updateVolume(mouse)
                    onPositionChanged: mouse => {
                        if (pressed)
                            updateVolume(mouse);
                    }
                    onClicked: mouse => updateVolume(mouse)

                    function updateVolume(mouse) {
                        if (!volumeAvailable)
                            return;
                        const ratio = 1.0 - (mouse.y / height);
                        const volume = Math.max(0, Math.min(1, ratio));
                        root.volumeChanged(volume);
                    }
                }
            }

            StyledText {
                anchors.bottom: parent.bottom
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.bottomMargin: Theme.spacingL
                text: volumeAvailable ? Math.round(currentVolume * 100) + "%" : "0%"
                font.pixelSize: Theme.fontSizeSmall
                color: Theme.surfaceText
                font.weight: Font.Medium
            }
        }
    }

    Rectangle {
        id: audioDevicesPanel
        visible: dropdownType === 2
        width: 280
        height: Math.max(200, Math.min(280, availableDevices.length * 50 + 100))
        x: isRightEdge ? anchorPos.x : anchorPos.x - width
        y: anchorPos.y - height / 2
        radius: Theme.cornerRadius * 2
        color: Theme.floatingSurface
        border.color: Theme.outlineStrong
        border.width: 2

        opacity: Theme.isDirectionalEffect ? 1 : (dropdownType === 2 ? 1 : 0)
        scale: Theme.isDirectionalEffect ? 1 : (dropdownType === 2 ? 1 : Theme.effectScaleCollapsed)
        transformOrigin: isRightEdge ? Item.Left : Item.Right

        Behavior on opacity {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                easing.type: Easing.BezierSpline
                duration: Math.round(Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 2) * Theme.variantOpacityDurationScale)
                easing.bezierCurve: dropdownType === 2 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        Behavior on scale {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 2)
                easing.type: Easing.BezierSpline
                easing.bezierCurve: dropdownType === 2 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        ElevationShadow {
            id: audioDevicesShadowLayer
            anchors.fill: parent
            z: -1
            level: Theme.elevationLevel2
            fallbackOffset: 4
            targetRadius: audioDevicesPanel.radius
            targetColor: audioDevicesPanel.color
            borderColor: audioDevicesPanel.border.color
            borderWidth: audioDevicesPanel.border.width
            shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
            shadowEnabled: Theme.elevationEnabled
        }

        MouseArea {
            anchors.fill: parent
            anchors.margins: -12
            hoverEnabled: true
            onEntered: panelAreaEntered()
            onExited: panelAreaExited()
        }

        Column {
            anchors.fill: parent
            anchors.margins: Theme.spacingM

            StyledText {
                text: I18n.tr("Audio Output Devices (") + availableDevices.length + ")"
                font.pixelSize: Theme.fontSizeMedium
                font.weight: Font.Medium
                color: Theme.surfaceText
                width: parent.width
                horizontalAlignment: Text.AlignHCenter
                bottomPadding: Theme.spacingM
            }

            DankFlickable {
                width: parent.width
                height: parent.height - 40
                contentHeight: deviceColumn.height
                clip: true

                Column {
                    id: deviceColumn
                    width: parent.width
                    spacing: Theme.spacingS

                    Repeater {
                        model: availableDevices
                        delegate: Rectangle {
                            required property var modelData
                            required property int index

                            width: parent.width
                            height: 48
                            radius: Theme.cornerRadius
                            color: deviceMouseArea.containsMouse ? Theme.primaryHover : Theme.nestedSurface
                            border.color: modelData === AudioService.sink ? Theme.primary : Theme.outlineHeavy
                            border.width: modelData === AudioService.sink ? 2 : 1

                            Row {
                                anchors.left: parent.left
                                anchors.leftMargin: Theme.spacingM
                                anchors.verticalCenter: parent.verticalCenter
                                spacing: Theme.spacingM
                                width: parent.width - Theme.spacingM * 2

                                DankIcon {
                                    name: getAudioDeviceIcon(modelData)
                                    size: 20
                                    color: modelData === AudioService.sink ? Theme.primary : Theme.surfaceText
                                    anchors.verticalCenter: parent.verticalCenter

                                    function getAudioDeviceIcon(device) {
                                        if (!device?.name)
                                            return "speaker";
                                        const name = device.name.toLowerCase();
                                        if (name.includes("bluez") || name.includes("bluetooth"))
                                            return "headset";
                                        if (name.includes("hdmi"))
                                            return "tv";
                                        if (name.includes("usb"))
                                            return "headset";
                                        return "speaker";
                                    }
                                }

                                Column {
                                    anchors.verticalCenter: parent.verticalCenter
                                    width: parent.width - 20 - Theme.spacingM * 2

                                    StyledText {
                                        text: AudioService.displayName(modelData)
                                        font.pixelSize: Theme.fontSizeMedium
                                        color: Theme.surfaceText
                                        font.weight: modelData === AudioService.sink ? Font.Medium : Font.Normal
                                        elide: Text.ElideRight
                                        wrapMode: Text.NoWrap
                                        width: parent.width
                                    }

                                    StyledText {
                                        text: {
                                            if (!modelData?.audio)
                                                return modelData === AudioService.sink ? I18n.tr("Active") : I18n.tr("Available");
                                            if (modelData.audio.muted)
                                                return I18n.tr("Muted", "audio status");
                                            return Math.round(modelData.audio.volume * 100) + "%";
                                        }
                                        font.pixelSize: Theme.fontSizeSmall
                                        color: Theme.surfaceVariantText
                                        elide: Text.ElideRight
                                        width: parent.width
                                    }
                                }
                            }

                            MouseArea {
                                id: deviceMouseArea
                                anchors.fill: parent
                                hoverEnabled: true
                                cursorShape: Qt.PointingHandCursor
                                acceptedButtons: Qt.LeftButton | Qt.RightButton
                                onPressed: mouse => {
                                    if (mouse.button === Qt.RightButton) {
                                        mouse.accepted = true;
                                    }
                                }
                                onWheel: wheelEvent => {
                                    if (!SettingsData.audioDeviceScrollVolumeEnabled || wheelEvent.x < deviceMouseArea.width / 2) {
                                        wheelEvent.accepted = false;
                                        return;
                                    }
                                    if (!modelData?.audio)
                                        return;
                                    SessionData.suppressOSDTemporarily();
                                    const delta = wheelEvent.angleDelta.y;
                                    if (delta === 0)
                                        return;
                                    const current = Math.round(modelData.audio.volume * 100);
                                    const maxVol = AudioService.getMaxVolumePercent(modelData);
                                    const newVolume = delta > 0 ? Math.min(maxVol, current + AudioService.wheelVolumeStep) : Math.max(0, current - AudioService.wheelVolumeStep);
                                    modelData.audio.muted = false;
                                    modelData.audio.volume = newVolume / 100;
                                    if (modelData === AudioService.sink)
                                        AudioService.playVolumeChangeSoundIfEnabled();
                                    wheelEvent.accepted = true;
                                }
                                onClicked: mouse => {
                                    if (mouse.button === Qt.RightButton) {
                                        if (modelData && modelData.audio) {
                                            SessionData.suppressOSDTemporarily();
                                            modelData.audio.muted = !modelData.audio.muted;
                                        }
                                        return;
                                    }
                                    if (modelData && modelData.name) {
                                        AudioService.setDefaultSinkByName(modelData.name);
                                        root.deviceSelected(modelData);
                                    }
                                }
                                onEntered: panelAreaEntered()
                                onExited: panelAreaExited()
                            }
                        }
                    }
                }
            }
        }
    }

    Rectangle {
        id: playersPanel
        visible: dropdownType === 3
        width: 240
        height: Math.max(180, Math.min(240, (root.selectablePlayers?.length || 0) * 50 + 80))
        x: isRightEdge ? anchorPos.x : anchorPos.x - width
        y: anchorPos.y - height / 2
        radius: Theme.cornerRadius * 2
        color: Theme.floatingSurface
        border.color: Theme.outlineStrong
        border.width: 2

        opacity: Theme.isDirectionalEffect ? 1 : (dropdownType === 3 ? 1 : 0)
        scale: Theme.isDirectionalEffect ? 1 : (dropdownType === 3 ? 1 : Theme.effectScaleCollapsed)
        transformOrigin: isRightEdge ? Item.Left : Item.Right

        Behavior on opacity {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                easing.type: Easing.BezierSpline
                duration: Math.round(Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 3) * Theme.variantOpacityDurationScale)
                easing.bezierCurve: dropdownType === 3 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        Behavior on scale {
            enabled: !Theme.isDirectionalEffect
            NumberAnimation {
                duration: Theme.variantDuration(Theme.expressiveDurations.expressiveDefaultSpatial, dropdownType === 3)
                easing.type: Easing.BezierSpline
                easing.bezierCurve: dropdownType === 3 ? Theme.variantPopoutEnterCurve : Theme.variantPopoutExitCurve
            }
        }

        ElevationShadow {
            id: playersShadowLayer
            anchors.fill: parent
            z: -1
            level: Theme.elevationLevel2
            fallbackOffset: 4
            targetRadius: playersPanel.radius
            targetColor: playersPanel.color
            borderColor: playersPanel.border.color
            borderWidth: playersPanel.border.width
            shadowOpacity: Theme.elevationLevel2 && Theme.elevationLevel2.alpha !== undefined ? Theme.elevationLevel2.alpha : 0.25
            shadowEnabled: Theme.elevationEnabled
        }

        MouseArea {
            anchors.fill: parent
            anchors.margins: -12
            hoverEnabled: true
            onEntered: panelAreaEntered()
            onExited: panelAreaExited()
        }

        Column {
            anchors.fill: parent
            anchors.margins: Theme.spacingM

            StyledText {
                text: I18n.tr("Media Players (") + (root.selectablePlayers?.length || 0) + ")"
                font.pixelSize: Theme.fontSizeMedium
                font.weight: Font.Medium
                color: Theme.surfaceText
                width: parent.width
                horizontalAlignment: Text.AlignHCenter
                bottomPadding: Theme.spacingM
            }

            DankFlickable {
                width: parent.width
                height: parent.height - 40
                contentHeight: playerColumn.height
                clip: true

                Column {
                    id: playerColumn
                    width: parent.width
                    spacing: Theme.spacingS

                    Repeater {
                        model: root.selectablePlayers || []
                        delegate: Rectangle {
                            required property var modelData
                            required property int index

                            width: parent.width
                            height: 48
                            radius: Theme.cornerRadius
                            color: playerMouseArea.containsMouse ? Theme.primaryHover : Theme.nestedSurface
                            border.color: modelData === activePlayer ? Theme.primary : Theme.outlineHeavy
                            border.width: modelData === activePlayer ? 2 : 1

                            Row {
                                anchors.left: parent.left
                                anchors.leftMargin: Theme.spacingM
                                anchors.verticalCenter: parent.verticalCenter
                                spacing: Theme.spacingM
                                width: parent.width - Theme.spacingM * 2

                                DankIcon {
                                    name: "music_note"
                                    size: 20
                                    color: modelData === activePlayer ? Theme.primary : Theme.surfaceText
                                    anchors.verticalCenter: parent.verticalCenter
                                }

                                Column {
                                    anchors.verticalCenter: parent.verticalCenter
                                    width: parent.width - 20 - Theme.spacingM * 2

                                    StyledText {
                                        text: {
                                            if (!modelData)
                                                return "Unknown Player";
                                            const identity = modelData.identity || "Unknown Player";
                                            const trackTitle = modelData.trackTitle || "";
                                            return trackTitle.length > 0 ? identity + " - " + trackTitle : identity;
                                        }
                                        font.pixelSize: Theme.fontSizeMedium
                                        color: Theme.surfaceText
                                        font.weight: modelData === activePlayer ? Font.Medium : Font.Normal
                                        elide: Text.ElideRight
                                        wrapMode: Text.NoWrap
                                        width: parent.width
                                    }

                                    StyledText {
                                        text: modelData?.trackArtist || I18n.tr("Unknown Artist")
                                        font.pixelSize: Theme.fontSizeSmall
                                        color: Theme.surfaceVariantText
                                        elide: Text.ElideRight
                                        wrapMode: Text.NoWrap
                                        width: parent.width
                                    }
                                }
                            }

                            MouseArea {
                                id: playerMouseArea
                                anchors.fill: parent
                                hoverEnabled: true
                                cursorShape: Qt.PointingHandCursor
                                onClicked: {
                                    if (modelData?.identity) {
                                        root.playerSelected(modelData);
                                    }
                                }
                                onEntered: panelAreaEntered()
                                onExited: panelAreaExited()
                            }
                        }
                    }
                }
            }
        }
    }
}
