import QtQuick
import QtQuick.Layouts
import Quickshell.Io

import "../../config" as Cfg
import "../../components"

ModuleChip {
    id: root

    width:  statsLayout.implicitWidth + 20
    chipColor:        t.statsBg
    chipBorderColor:  t.statsBorder

    Behavior on width {
        NumberAnimation { duration: 250; easing.type: Easing.OutCubic }
    }

    property bool expanded: Cfg.Config.statsStartExpanded

    TapHandler {
        onTapped: {
            root.expanded = !root.expanded
            if (!root.expanded) root.hovered = false
        }
    }

    property real cpuVal:  0
    property real memVal:  0
    property real diskVal: 0
    property real cpuTemp:  -1
    property real gpuTemp:  -1

    Timer {
        interval: 2000
        running: true
        repeat: true
        triggeredOnStart: true
        onTriggered: { statsProc.running = true }
    }

    Process {
        id: statsProc
        command: ["sh", "-c",
            "(head -n 1 /proc/stat; sleep 1; head -n 1 /proc/stat) | awk " +
            "'{u=$2+$3;s=$4;i=$5+$6;x=$7+$8;t=u+s+i+x;if(NR==1){p=t;q=i;next}" +
            "{dt=t-p;di=i-q;print (dt>0?100*(dt-di)/dt:0)}}'; " +
            "awk '/MemTotal/{t=$2}/MemAvailable/{a=$2}END" +
            "{print (t>0?(t-a)/t*100:0)}' /proc/meminfo; " +
            "df / | awk 'NR==2{sub(/%/,\"\",$5); print $5}'; " +
            "ct=-1; for d in /sys/class/hwmon/hwmon*; do " +
            "n=$(cat $d/name 2>/dev/null); " +
            "if echo \"$n\" | grep -qiE " +
            "'coretemp|k10temp|cpu_thermal|zenpower|acpitz|x86_pkg_temp|thinkpad|nct6775'; then " +
            "ct=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " +
            "fi; done; echo $ct; " +
            "gt=-1; for d in /sys/class/hwmon/hwmon*; do " +
            "n=$(cat $d/name 2>/dev/null); " +
            "if echo \"$n\" | grep -qiE 'amdgpu|radeon|nouveau'; then " +
            "gt=$(( $(cat $d/temp1_input 2>/dev/null) / 1000 )); break; " +
            "fi; done; " +
            "[ \"$gt\" = \"-1\" ] && " +
            "gt=$(nvidia-smi --query-gpu=temperature.gpu " +
            "--format=csv,noheader 2>/dev/null | head -n 1); " +
            "echo $gt"]
        property string rawOutput: ""
        stdout: SplitParser {
            onRead: data => { statsProc.rawOutput += data + "\n" }
        }
        onRunningChanged: {
            if (!statsProc.running && statsProc.rawOutput) {
                const lines = statsProc.rawOutput.trim().split("\n")
                if (lines.length >= 5) {
                    let v = parseFloat(lines[0]); root.cpuVal  = isNaN(v) ? 0 : v
                    v = parseFloat(lines[1]); root.memVal  = isNaN(v) ? 0 : v
                    v = parseFloat(lines[2]); root.diskVal = isNaN(v) ? 0 : v
                    v = parseFloat(lines[3]); root.cpuTemp = isNaN(v) ? -1 : v
                    v = parseFloat(lines[4]); root.gpuTemp = isNaN(v) ? -1 : v
                }
                statsProc.rawOutput = ""
            }
        }
    }

    component StatRing: RowLayout {
        id: ring
        spacing: 5

        property real   value:      0.0
        property string icon:       ""
        property string label:      ""
        property real   iconXOff:   0
        property color  ringColor:  Cfg.Config.theme.accent
        property color  trackColor: Cfg.Config.theme.statsTrackColor
        property string labelSuffix:"%"

        Behavior on value {
            NumberAnimation { duration: 800; easing.type: Easing.OutCubic }
        }

        readonly property real fraction: Math.max(0, Math.min(value, 100)) / 100

        Text {
            id: leftPct
            text:             Math.round(ring.value) + ring.labelSuffix
            color:            ring.ringColor
            font.pixelSize:   Cfg.Config.statsRingFontSize
            font.bold:        true
            font.family:      "monospace"
            Layout.alignment: Qt.AlignVCenter
            clip:             true

            readonly property bool active: Cfg.Config.statsLabelPosition === "left" && (root.expanded || root.hovered)
            opacity:               active ? 1 : 0
            Layout.preferredWidth: active ? implicitWidth : 0

            Behavior on opacity               { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
            Behavior on Layout.preferredWidth { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
        }

        Item {
            id: ringCore
            Layout.preferredWidth:  Cfg.Config.statsRingSize
            Layout.preferredHeight: Cfg.Config.statsRingSize

            onVisibleChanged: if (visible) arc.requestPaint()

            Canvas {
                id: arc
                anchors.fill: parent
                antialiasing: true

                Connections {
                    target: ring
                    function onFractionChanged()  { arc.requestPaint() }
                    function onRingColorChanged() { arc.requestPaint() }
                }

                onPaint: {
                    var ctx = getContext("2d")
                    ctx.reset()

                    var cx = width / 2
                    var cy = height / 2
                    var lw = 2.8
                    var r  = Math.min(cx, cy) - lw / 2 - 0.5

                    ctx.beginPath()
                    ctx.arc(cx, cy, r, 0, Math.PI * 2)
                    ctx.strokeStyle = ring.trackColor
                    ctx.lineWidth = lw
                    ctx.stroke()

                    if (ring.fraction > 0) {
                        var start = -Math.PI / 2
                        var end   = start + (ring.fraction * Math.PI * 2)
                        ctx.beginPath()
                        ctx.arc(cx, cy, r, start, end)
                        ctx.strokeStyle = ring.ringColor
                        ctx.lineWidth = lw
                        ctx.lineCap = "round"
                        ctx.stroke()
                    }
                }
            }

            Text {
                anchors.centerIn: parent
                anchors.horizontalCenterOffset: ring.iconXOff
                text:           ring.icon
                color:          ring.ringColor
                font.pixelSize: Cfg.Config.statsIconSize
            }
        }

        Text {
            id: rightPct
            text:             Math.round(ring.value) + ring.labelSuffix
            color:            ring.ringColor
            font.pixelSize:   Cfg.Config.statsRingFontSize
            font.bold:        true
            font.family:      "monospace"
            Layout.alignment: Qt.AlignVCenter
            clip:             true

            readonly property bool active: Cfg.Config.statsLabelPosition === "right" && (root.expanded || root.hovered)
            opacity:               active ? 1 : 0
            Layout.preferredWidth: active ? implicitWidth : 0

            Behavior on opacity               { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
            Behavior on Layout.preferredWidth { NumberAnimation { duration: 200; easing.type: Easing.OutCubic } }
        }
    }

    RowLayout {
        id: statsLayout
        anchors.centerIn: parent
        spacing: 8

        StatRing {
            visible:    Cfg.Config.statsShowCpu
            value:      root.cpuVal
            icon:       "󰍛"
            label:      "CPU"
            iconXOff:   0.3
            ringColor:  root.t.statsCpuColor
            trackColor: root.t.statsTrackColor
        }

        StatRing {
            visible:    Cfg.Config.statsShowMem
            value:      root.memVal
            icon:       "󰑭"
            label:      "RAM"
            ringColor:  root.t.statsMemColor
            trackColor: root.t.statsTrackColor
        }

        StatRing {
            visible:    Cfg.Config.statsShowDisk
            value:      root.diskVal
            icon:       "󰒋"
            label:      "DISK"
            ringColor:  root.t.statsDiskColor
            trackColor: root.t.statsTrackColor
        }

        StatRing {
            visible:    Cfg.Config.statsShowCpuTemp && root.cpuTemp >= 0
            value:      root.cpuTemp
            icon:       "󰔄"
            label:      "CPU°C"
            ringColor:  root.t.statsCpuTempColor
            trackColor: root.t.statsTrackColor
            labelSuffix: "°C"
        }

        StatRing {
            visible:    Cfg.Config.statsShowGpuTemp && root.gpuTemp >= 0
            value:      root.gpuTemp
            icon:       "󰾲"
            label:      "GPU°C"
            ringColor:  root.t.statsGpuColor
            trackColor: root.t.statsTrackColor
            labelSuffix: "°C"
        }
    }
}
