import QtQuick
import Quickshell
import Quickshell.Io
import qs.config
pragma Singleton

Singleton {
    id: root

    property string hostname: ""
    property string username: ""
    property string osIcon: ""
    property string osName: ""
    property string kernelVersion: ""
    property string architecture: ""
    property string uptime: ""
    property string qsVersion: ""
    property string swapUsage: "—"
    property real swapPercent: 0
    property string ipAddress: "—"
    property int runningProcesses: 0
    property int loggedInUsers: 0
    property string ramUsage: "—"
    property real ramPercent: 0
    property string cpuLoad: "—"
    property real cpuPercent: 0
    property string diskUsage: "—"
    property real diskPercent: 0
    property string cpuTemp: "—"
    property string keyboardLayout: "none"
    property real cpuTempPercent: 0
    property int prevIdle: -1
    property int prevTotal: -1


    readonly property var osIcons: ({
        "almalinux": "",
        "alpine": "",
        "arch": "󰣇",
        "archcraft": "",
        "arcolinux": "",
        "artix": "",
        "centos": "",
        "debian": "",
        "devuan": "",
        "elementary": "",
        "endeavouros": "",
        "fedora": "",
        "freebsd": "",
        "garuda": "",
        "gentoo": "",
        "hyperbola": "",
        "kali": "",
        "linuxmint": "󰣭",
        "mageia": "",
        "openmandriva": "",
        "manjaro": "",
        "neon": "",
        "nixos": "",
        "opensuse": "",
        "suse": "",
        "sles": "",
        "sles_sap": "",
        "opensuse-tumbleweed": "",
        "parrot": "",
        "pop": "",
        "raspbian": "",
        "rhel": "",
        "rocky": "",
        "slackware": "",
        "solus": "",
        "steamos": "",
        "tails": "",
        "trisquel": "",
        "ubuntu": "",
        "vanilla": "",
        "void": "",
        "zorin": "",
        "opensuse": "",

    })


    FileView { id: cpuStat; path: "/proc/stat" }
    FileView { id: memInfo; path: "/proc/meminfo" }
    FileView { id: uptimeFile; path: "/proc/uptime" }


    Timer {
        interval: 1000
        running: true
        repeat: true

        onTriggered: {

            cpuStat.reload()
            memInfo.reload()
            uptimeFile.reload()

            /* CPU */

            const cpuLine = cpuStat.text().split("\n")[0].trim().split(/\s+/)

            const cpuUser = parseInt(cpuLine[1])
            const cpuNice = parseInt(cpuLine[2])
            const cpuSystem = parseInt(cpuLine[3])
            const cpuIdle = parseInt(cpuLine[4])
            const cpuIowait = parseInt(cpuLine[5])
            const cpuIrq = parseInt(cpuLine[6])
            const cpuSoftirq = parseInt(cpuLine[7])

            const cpuIdleAll = cpuIdle + cpuIowait
            const cpuTotal =
                cpuUser + cpuNice + cpuSystem + cpuIrq + cpuSoftirq + cpuIdleAll

            if (root.prevTotal >= 0) {

                const totalDiff = cpuTotal - root.prevTotal
                const idleDiff = cpuIdleAll - root.prevIdle

                if (totalDiff > 0)
                    root.cpuPercent = (totalDiff - idleDiff) / totalDiff
            }

            root.prevTotal = cpuTotal
            root.prevIdle = cpuIdleAll

            root.cpuLoad = Math.round(root.cpuPercent * 100) + "%"


            /* RAM */

            const memLines = memInfo.text().split("\n")

            let memTotal = 0
            let memAvailable = 0

            for (let line of memLines) {

                if (line.startsWith("MemTotal"))
                    memTotal = parseInt(line.match(/\d+/)[0])

                if (line.startsWith("MemAvailable"))
                    memAvailable = parseInt(line.match(/\d+/)[0])
            }

            if (memTotal > 0) {

                const memUsed = memTotal - memAvailable

                root.ramPercent = memUsed / memTotal
                root.ramUsage =
                    `${Math.round(memUsed/1024)}/${Math.round(memTotal/1024)} MB`
            }


            /* Uptime */

            const uptimeSeconds =
                parseFloat(uptimeFile.text().split(" ")[0])

            const d = Math.floor(uptimeSeconds / 86400)
            const h = Math.floor((uptimeSeconds % 86400) / 3600)
            const m = Math.floor((uptimeSeconds % 3600) / 60)

            let upString = "Up "

            if (d > 0) upString += d + "d "
            if (h > 0) upString += h + "h "

            upString += m + "m"

            root.uptime = upString


            cpuTempProc.running = true
            diskProc.running = true
            ipProc.running = true
            procCountProc.running = true
            swapProc.running = true
            keyboardLayoutProc.running = true
            loggedUsersProc.running = true
        }
    }


    /* CPU Temperature */

    Process {
        id: cpuTempProc
        command: [
            "sh","-c",
            "for f in /sys/class/hwmon/hwmon*/temp*_input; do cat $f && exit; done"
        ]

        stdout: StdioCollector {
            onStreamFinished: {
                const raw = parseInt(text.trim())
                if (isNaN(raw)) return

                const c = raw / 1000
                root.cpuTemp = `${Math.round(c)}°C`

                const min = 30
                const max = 95

                root.cpuTempPercent =
                    Math.max(0, Math.min(1,(c-min)/(max-min)))
            }
        }
    }


    /* Disk */

    Process {
        id: diskProc
        command: ["df","-h","/"]

        stdout: StdioCollector {
            onStreamFinished: {

                const lines = text.trim().split("\n")
                if (lines.length < 2) return

                const parts = lines[1].split(/\s+/)

                const used = parts[2]
                const total = parts[1]
                const percent = parseInt(parts[4]) / 100

                root.diskPercent = percent
                root.diskUsage = `${used}/${total}`
            }
        }
    }


    /* Swap */

    Process {
        id: swapProc
        command: ["sh","-c","free -m | grep Swap"]

        stdout: StdioCollector {
            onStreamFinished: {

                const parts = text.trim().split(/\s+/)
                if (parts.length < 3) return

                const total = parseInt(parts[1])
                const used = parseInt(parts[2])

                root.swapPercent = used / total
                root.swapUsage = `${used}/${total} MB`
            }
        }
    }


    /* IP */

    Process {
        id: ipProc
        command: ["sh","-c","hostname -I | awk '{print $1}'"]

        stdout: StdioCollector {
            onStreamFinished: root.ipAddress = text.trim()
        }
    }


    /* Process Count */

    Process {
        id: procCountProc
        command: ["sh","-c","ps -e --no-headers | wc -l"]

        stdout: StdioCollector {
            onStreamFinished: root.runningProcesses = parseInt(text.trim())
        }
    }


    /* Logged Users */

    Process {
        id: loggedUsersProc
        command: ["who","-q"]

        stdout: StdioCollector {
            onStreamFinished: {
                const lines = text.trim().split("\n")
                if (lines.length > 0)
                    root.loggedInUsers =
                        parseInt(lines[lines.length-1].replace("# users=",""))
            }
        }
    }


    /* Keyboard Layout */

    Process {
        id: keyboardLayoutProc
        command: [
            "sh","-c",
            "hyprctl devices -j | jq -r '.keyboards[] | .layout' | head -n1"
        ]

        stdout: StdioCollector {
            onStreamFinished: {
                const layout = text.trim()
                if (layout)
                    root.keyboardLayout = layout
            }
        }
    }


    /* OS Info */

    Process {
        running: true
        command: [
            "sh","-c",
            "source /etc/os-release && echo \"$PRETTY_NAME|$ID\""
        ]

        stdout: StdioCollector {
            onStreamFinished: {
                const parts = text.trim().split("|")
                root.osName = parts[0]
                root.osIcon = root.osIcons[parts[1]] || ""
            }
        }
    }


    /* Quickshell Version */

    Process {
        running: true
        command: ["qs","--version"]

        stdout: StdioCollector {
            onStreamFinished: {
                root.qsVersion =
                    text.trim().split(',')[0]
                    .replace("quickshell ","")
            }
        }
    }


    /* Static system info */

    Process {
        running: true
        command: ["whoami"]

        stdout: StdioCollector {
            onStreamFinished: root.username = text.trim()
        }
    }

    Process {
        running: true
        command: ["hostname"]

        stdout: StdioCollector {
            onStreamFinished: root.hostname = text.trim()
        }
    }

    Process {
        running: true
        command: ["uname","-r"]

        stdout: StdioCollector {
            onStreamFinished: root.kernelVersion = text.trim()
        }
    }

    Process {
        running: true
        command: ["uname","-m"]

        stdout: StdioCollector {
            onStreamFinished: root.architecture = text.trim()
        }
    }

}
