import QtQuick
import QtQuick.Layouts
import Quickshell
import qs.modules.common
import qs.modules.common.widgets
import qs.modules.common.utils
import qs.modules.icons
import qs.services

Item {
    id: root

    property real scale: Config.data.ram.scale || 1.0

    implicitWidth: (icon.visible ? icon.width : 0)
        + (graph.visible ? graph.width : 0) + 4
    implicitHeight: Config.data.bar.size - Config.data.bar.size * 0.2

    RAMIcon {
        id: icon
        visible: Config.data.ram.icon.enabled
        color: Config.data.ram.icon.color
        scale: Config.data.ram.icon.scale * root.height
        anchors.verticalCenter: parent.verticalCenter
    }

    Canvas {
        id: graph
        visible: Config.data.ram.graph.enabled
        anchors {
            top: parent.top
            bottom: parent.bottom
            right: parent.right
        }
        width: 100 * root.scale

        onPaint: {
            if (RAM.total === 0) return;

            let ctx = getContext("2d");
            ctx.clearRect(0, 0, width, height);

            let usedRatio = RAM.used / RAM.total;
            let sharedRatio = RAM.shared / RAM.total;
            let buffersCachedRatio = (RAM.buffers + RAM.cached + RAM.sreclaimable) / RAM.total;
            let freeRatio = RAM.free / RAM.total;

            // Clamp small ratios to minimum visible width
            let minVisible = 1 / width;
            usedRatio = Math.max(usedRatio, minVisible);
            sharedRatio = Math.max(sharedRatio, minVisible);
            buffersCachedRatio = Math.max(buffersCachedRatio, minVisible);
            freeRatio = Math.max(freeRatio, minVisible);

            let cumulativeX = 0;

            // Draw segments from left to right
            if (usedRatio > 0) {
                ctx.fillStyle = Config.data.ram.colors.used;
                ctx.fillRect(cumulativeX, 0, usedRatio * width, height);
                cumulativeX += usedRatio * width;
            }
            if (sharedRatio > 0) {
                ctx.fillStyle = Config.data.ram.colors.shared;
                ctx.fillRect(cumulativeX, 0, sharedRatio * width, height);
                cumulativeX += sharedRatio * width;
            }
            if (buffersCachedRatio > 0) {
                ctx.fillStyle = Config.data.ram.colors.buffersCached;
                ctx.fillRect(cumulativeX, 0, buffersCachedRatio * width, height);
                cumulativeX += buffersCachedRatio * width;
            }
            if (freeRatio > 0) {
                ctx.fillStyle = Config.data.ram.colors.free;
                ctx.fillRect(cumulativeX, 0, freeRatio * width, height);
            }
        }
    }

    Connections {
        target: RAM
        function onStatsUpdated() {
            graph.requestPaint()
        }
    }

    HoverPopup {
        anchors.centerIn: root
        hoverTarget: root
        anchorPosition: Types.stringToPosition(Config.data.bar.position)
        contentComponent: Component {
            ColumnLayout {
                id: contentColumn
                spacing: 2

                Text {
                    Layout.alignment: Qt.AlignHCenter
                    text: "RAM Usage"
                    font.family: Config.data.theme.font.family
                    font.pixelSize: Config.data.theme.font.size
                    font.bold: true
                    color: Config.data.theme.colors.foreground
                }

                Text {
                    Layout.alignment: Qt.AlignHCenter
                    font.family: Config.data.theme.font.family
                    font.pixelSize: Config.data.theme.font.size
                    color: Config.data.theme.colors.foreground
                    textFormat: Text.RichText

                    text: {
                        let rows = [
                            {
                                label: "Total",
                                source: ['total'],
                                color: Config.data.theme.colors.foreground,
                            },
                            {
                                label: "Used",
                                source: ['used'],
                                color: Config.data.ram.colors.used,
                            },
                            {
                                label: "Shared",
                                source: ['shared'],
                                color: Config.data.ram.colors.shared,
                            },
                            {
                                label: "Buff/Cache",
                                source: ['buffers', 'cached', 'sreclaimable'],
                                color: Config.data.ram.colors.buffersCached,
                            },
                            {
                                label: "Free",
                                source: ['free'],
                                color: Config.data.ram.colors.free,
                            },
                            {
                                label: "Available",
                                source: ['available'],
                                color: Config.data.theme.colors.foreground,
                            },
                        ];

                        let total = FileUtils.convertSizeUnit(RAM.total, "KiB", Config.data.ram.sizeUnit);

                        for (let i = 0; i < rows.length; ++i) {
                            let val = 0.0;
                            for (let j = 0; j < rows[i].source.length; ++j) {
                                val += RAM[rows[i].source[j]];
                            }
                            if (rows[i].label === 'Total') {
                                rows[i].value = total;
                            } else {
                                rows[i].value = FileUtils.convertSizeUnit(val, "KiB", Config.data.ram.sizeUnit);
                                rows[i].pct = (rows[i].value / total)*100;
                            }
                        }

                        let createRow = function(rowData) {
                            return `
<tr>
  <td align="left" width="60"><span style="color: ${rowData.color}">${rowData.label}</span>:</td>
  <td align="right" width="70"><span style="font-family: '${Config.data.theme.fontMono.family}'; font-size: ${Config.data.theme.fontMono.size}px;">${rowData.value.toFixed(2)}${Config.data.ram.sizeUnit}</span></td>
  <td align="right" width="60"><span style="font-family: '${Config.data.theme.fontMono.family}'; font-size: ${Config.data.theme.fontMono.size}px;">${typeof rowData.pct !== 'undefined' ? rowData.pct.toFixed(2) + "%" : ""}</span></td>
</tr>`;
                        };

                        return `<table>${rows.map(r => createRow(r)).join("")}</table>`;
                    }
                }

                Text {
                    Layout.alignment: Qt.AlignHCenter
                    text: "Top Processes"
                    font.family: Config.data.theme.font.family
                    font.pixelSize: Config.data.theme.font.size
                    font.bold: true
                    color: Config.data.theme.colors.foreground
                    Layout.topMargin: 6
                }

                Text {
                    Layout.alignment: Qt.AlignHCenter
                    font.family: Config.data.theme.fontMono.family
                    font.pixelSize: Config.data.theme.fontMono.size
                    color: Config.data.theme.colors.foreground
                    text: {
                        let out = [];
                        for (let p of RAM.topProcesses) {
                            let pidStr = p.pid.toString().padStart(6);
                            let commStr = p.comm.slice(0, 15).padEnd(15);
                            let memStr = `${p.mem.toFixed(1)}%`;
                            out.push(`${pidStr} ${commStr}\t${memStr.padStart(6)}`);
                        }
                        return out.join("\n");
                    }
                }
            }
        }
    }
}