import QtQuick
import QtQuick.Effects
import QtQuick.Shapes
import Quickshell.Services.Mpris
import qs.Common
import qs.Services
import qs.Widgets

Card {
    id: root
    signal clicked()

    property MprisPlayer activePlayer: MprisController.activePlayer
    property real currentPosition: activePlayer?.positionSupported ? activePlayer.position : 0
    property real displayPosition: currentPosition

    readonly property real ratio: {
        if (!activePlayer || activePlayer.length <= 0) return 0
        const calculatedRatio = displayPosition / activePlayer.length
        return Math.max(0, Math.min(1, calculatedRatio))
    }

    onActivePlayerChanged: {
        if (activePlayer?.positionSupported) {
            currentPosition = Qt.binding(() => activePlayer?.position || 0)
        } else {
            currentPosition = 0
        }
    }

    Timer {
        interval: 300
        running: activePlayer?.playbackState === MprisPlaybackState.Playing && !progressMouseArea.isSeeking
        repeat: true
        onTriggered: activePlayer?.positionSupported && activePlayer.positionChanged()
    }

    Column {
        anchors.centerIn: parent
        spacing: Theme.spacingS
        visible: !activePlayer

        DankIcon {
            name: "music_note"
            size: Theme.iconSize
            color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.5)
            anchors.horizontalCenter: parent.horizontalCenter
        }

        StyledText {
            text: "No Media"
            font.pixelSize: Theme.fontSizeSmall
            color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }

    Column {
        anchors.centerIn: parent
        width: parent.width - Theme.spacingXS * 2
        spacing: Theme.spacingL
        visible: activePlayer

        Item {
            width: 110
            height: 80
            anchors.horizontalCenter: parent.horizontalCenter

            Loader {
                active: activePlayer?.playbackState === MprisPlaybackState.Playing
                sourceComponent: Component {
                    Ref {
                        service: CavaService
                    }
                }
            }

            Shape {
                id: morphingBlob
                width: 120
                height: 120
                anchors.centerIn: parent
                visible: activePlayer?.playbackState === MprisPlaybackState.Playing
                asynchronous: false
                antialiasing: true
                preferredRendererType: Shape.CurveRenderer
                
                layer.enabled: true
                layer.smooth: true
                layer.samples: 4
                
                
                readonly property real centerX: width / 2
                readonly property real centerY: height / 2
                readonly property real baseRadius: 40
                readonly property int segments: 24
                
                property var audioLevels: {
                    if (!CavaService.cavaAvailable || CavaService.values.length === 0) {
                        return [0.5, 0.3, 0.7, 0.4, 0.6, 0.5]
                    }
                    return CavaService.values
                }
                
                property var smoothedLevels: [0.5, 0.3, 0.7, 0.4, 0.6, 0.5]
                property var cubics: []

                
                onAudioLevelsChanged: updatePath()
                
                Timer {
                    running: morphingBlob.visible
                    interval: 16
                    repeat: true
                    onTriggered: morphingBlob.updatePath()
                }
                
                Component {
                    id: cubicSegment
                    PathCubic {}
                }
                
                Component.onCompleted: {
                    shapePath.pathElements.push(Qt.createQmlObject(
                        'import QtQuick; import QtQuick.Shapes; PathMove {}', shapePath
                    ))
                    
                    for (let i = 0; i < segments; i++) {
                        const seg = cubicSegment.createObject(shapePath)
                        shapePath.pathElements.push(seg)
                        cubics.push(seg)
                    }
                    
                    updatePath()
                }
                
                function expSmooth(prev, next, alpha) {
                    return prev + alpha * (next - prev)
                }
                
                function updatePath() {
                    if (cubics.length === 0) return
                    
                    for (let i = 0; i < Math.min(smoothedLevels.length, audioLevels.length); i++) {
                        smoothedLevels[i] = expSmooth(smoothedLevels[i], audioLevels[i], 0.2)
                    }
                    
                    const points = []
                    for (let i = 0; i < segments; i++) {
                        const angle = (i / segments) * 2 * Math.PI
                        const audioIndex = i % Math.min(smoothedLevels.length, 6)
                        const audioLevel = Math.max(0.1, Math.min(1.5, (smoothedLevels[audioIndex] || 0) / 50))
                        
                        const radius = baseRadius * (1.0 + audioLevel * 0.3)
                        const x = centerX + Math.cos(angle) * radius
                        const y = centerY + Math.sin(angle) * radius
                        points.push({x: x, y: y})
                    }
                    
                    const startMove = shapePath.pathElements[0]
                    startMove.x = points[0].x
                    startMove.y = points[0].y
                    
                    const tension = 0.5
                    for (let i = 0; i < segments; i++) {
                        const p0 = points[(i - 1 + segments) % segments]
                        const p1 = points[i]
                        const p2 = points[(i + 1) % segments]
                        const p3 = points[(i + 2) % segments]
                        
                        const c1x = p1.x + (p2.x - p0.x) * tension / 3
                        const c1y = p1.y + (p2.y - p0.y) * tension / 3
                        const c2x = p2.x - (p3.x - p1.x) * tension / 3
                        const c2y = p2.y - (p3.y - p1.y) * tension / 3
                        
                        const seg = cubics[i]
                        seg.control1X = c1x
                        seg.control1Y = c1y
                        seg.control2X = c2x
                        seg.control2Y = c2y
                        seg.x = p2.x
                        seg.y = p2.y
                    }
                }
                
                ShapePath {
                    id: shapePath
                    fillColor: Theme.primary
                    strokeColor: "transparent"
                    strokeWidth: 0
                    joinStyle: ShapePath.RoundJoin
                    fillRule: ShapePath.WindingFill
                }
            }

            Rectangle {
                width: 72
                height: 72
                radius: 36
                color: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.3)
                border.color: Theme.surfaceContainer
                border.width: 1
                anchors.horizontalCenter: parent.horizontalCenter
                anchors.verticalCenter: parent.verticalCenter
                z: 1

                Image {
                    id: albumArt
                    source: activePlayer?.trackArtUrl || ""
                    anchors.fill: parent
                    anchors.margins: 2
                    fillMode: Image.PreserveAspectCrop
                    smooth: true
                    mipmap: true
                    cache: true
                    asynchronous: true
                    visible: false
                }

                MultiEffect {
                    anchors.fill: parent
                    anchors.margins: 2
                    source: albumArt
                    maskEnabled: true
                    maskSource: circularMask
                    visible: albumArt.status === Image.Ready
                    maskThresholdMin: 0.5
                    maskSpreadAtMin: 1
                }

                Item {
                    id: circularMask
                    width: 68
                    height: 68
                    layer.enabled: true
                    layer.smooth: true
                    visible: false

                    Rectangle {
                        anchors.fill: parent
                        radius: width / 2
                        color: "black"
                        antialiasing: true
                    }
                }

                DankIcon {
                    anchors.centerIn: parent
                    name: "album"
                    size: 20
                    color: Theme.surfaceVariantText
                    visible: albumArt.status !== Image.Ready
                }
            }
        }

        Column {
            width: parent.width
            spacing: Theme.spacingXS
            topPadding: Theme.spacingL

            StyledText {
                text: activePlayer?.trackTitle || "Unknown"
                font.pixelSize: Theme.fontSizeSmall
                font.weight: Font.Medium
                color: Theme.surfaceText
                width: parent.width
                elide: Text.ElideRight
                maximumLineCount: 1
                horizontalAlignment: Text.AlignHCenter
            }

            StyledText {
                text: activePlayer?.trackArtist || "Unknown Artist"
                font.pixelSize: Theme.fontSizeSmall
                color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.7)
                width: parent.width
                elide: Text.ElideRight
                maximumLineCount: 1
                horizontalAlignment: Text.AlignHCenter
            }
        }

        Item {
            id: progressSlider
            width: parent.width
            height: 20
            visible: activePlayer?.length > 0

            property real value: ratio
            property real lineWidth: 2.5
            property color trackColor: Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.40)
            property color fillColor: Theme.primary
            property color playheadColor: Theme.primary

            Rectangle {
                width: parent.width
                height: progressSlider.lineWidth
                anchors.verticalCenter: parent.verticalCenter
                color: progressSlider.trackColor
                radius: height / 2
            }

            Rectangle {
                width: Math.max(0, Math.min(parent.width, parent.width * progressSlider.value))
                height: progressSlider.lineWidth
                anchors.left: parent.left
                anchors.verticalCenter: parent.verticalCenter
                color: progressSlider.fillColor
                radius: height / 2
                Behavior on width { NumberAnimation { duration: 80 } }
            }

            Rectangle {
                id: playhead
                width: 2.5
                height: Math.max(progressSlider.lineWidth + 8, 12)
                radius: width / 2
                color: progressSlider.playheadColor
                x: Math.max(0, Math.min(progressSlider.width, progressSlider.width * progressSlider.value)) - width / 2
                anchors.verticalCenter: parent.verticalCenter
                z: 3
                Behavior on x { NumberAnimation { duration: 80 } }
            }

            MouseArea {
                id: progressMouseArea
                anchors.fill: parent
                hoverEnabled: true
                cursorShape: Qt.PointingHandCursor
                enabled: activePlayer ? (activePlayer.canSeek && activePlayer.length > 0) : false

                property bool isSeeking: false
                property real pendingSeekPosition: -1

                Timer {
                    id: seekDebounceTimer
                    interval: 150
                    onTriggered: {
                        if (progressMouseArea.pendingSeekPosition >= 0 && activePlayer?.canSeek && activePlayer?.length > 0) {
                            const clamped = Math.min(progressMouseArea.pendingSeekPosition, activePlayer.length * 0.99)
                            activePlayer.position = clamped
                            progressMouseArea.pendingSeekPosition = -1
                        }
                    }
                }

                onPressed: (mouse) => {
                    isSeeking = true
                    if (activePlayer?.length > 0 && activePlayer?.canSeek) {
                        const r = Math.max(0, Math.min(1, mouse.x / progressSlider.width))
                        pendingSeekPosition = r * activePlayer.length
                        displayPosition = pendingSeekPosition
                        seekDebounceTimer.restart()
                    }
                }
                onReleased: {
                    isSeeking = false
                    seekDebounceTimer.stop()
                    if (pendingSeekPosition >= 0 && activePlayer?.canSeek && activePlayer?.length > 0) {
                        const clamped = Math.min(pendingSeekPosition, activePlayer.length * 0.99)
                        activePlayer.position = clamped
                        pendingSeekPosition = -1
                    }
                    displayPosition = Qt.binding(() => currentPosition)
                }
                onPositionChanged: (mouse) => {
                    if (pressed && isSeeking && activePlayer?.length > 0 && activePlayer?.canSeek) {
                        const r = Math.max(0, Math.min(1, mouse.x / progressSlider.width))
                        pendingSeekPosition = r * activePlayer.length
                        displayPosition = pendingSeekPosition
                        seekDebounceTimer.restart()
                    }
                }
                onClicked: (mouse) => {
                    if (activePlayer?.length > 0 && activePlayer?.canSeek) {
                        const r = Math.max(0, Math.min(1, mouse.x / progressSlider.width))
                        activePlayer.position = r * activePlayer.length
                    }
                }
            }
        }

        Item {
            width: parent.width
            height: 32

            Row {
                spacing: Theme.spacingS
                anchors.centerIn: parent

            Rectangle {
                width: 28
                height: 28
                radius: 14
                anchors.verticalCenter: playPauseButton.verticalCenter
                color: prevArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"

                DankIcon {
                    anchors.centerIn: parent
                    name: "skip_previous"
                    size: 14
                    color: Theme.surfaceText
                }

                MouseArea {
                    id: prevArea
                    anchors.fill: parent
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    onClicked: {
                        if (!activePlayer) return
                        if (activePlayer.position > 8 && activePlayer.canSeek) {
                            activePlayer.position = 0
                        } else {
                            activePlayer.previous()
                        }
                    }
                }
            }

            Rectangle {
                id: playPauseButton
                width: 32
                height: 32
                radius: 16
                color: Theme.primary

                DankIcon {
                    anchors.centerIn: parent
                    name: activePlayer?.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow"
                    size: 16
                    color: Theme.background
                }

                MouseArea {
                    anchors.fill: parent
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    onClicked: activePlayer?.togglePlaying()
                }
            }

            Rectangle {
                width: 28
                height: 28
                radius: 14
                anchors.verticalCenter: playPauseButton.verticalCenter
                color: nextArea.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.12) : "transparent"

                DankIcon {
                    anchors.centerIn: parent
                    name: "skip_next"
                    size: 14
                    color: Theme.surfaceText
                }

                MouseArea {
                    id: nextArea
                    anchors.fill: parent
                    hoverEnabled: true
                    cursorShape: Qt.PointingHandCursor
                    onClicked: activePlayer?.next()
                }
            }
            }
        }
    }

    MouseArea {
        anchors.top: parent.top
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 123
        hoverEnabled: true
        cursorShape: Qt.PointingHandCursor
        onClicked: root.clicked()
        visible: activePlayer
    }
}