using System.Management;
using System.Runtime.InteropServices;

namespace Lentia.Utils;

public class RamMetrics {
    public double TotalGb { get; set; }
    public double FreeGb { get; set; }
}

public static class Hardware {
    public static RamMetrics GetRamUsage() {
        var metrics = new RamMetrics();

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
            GetWindowsRam(metrics);
        } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) {
            GetLinuxRam(metrics);
        } else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) {
            GetMacRam(metrics);
        }

        return metrics;
    }

    private static void GetWindowsRam(RamMetrics metrics) {
        try {
            using var searcherTotal = new ManagementObjectSearcher("SELECT TotalPhysicalMemory FROM Win32_ComputerSystem");
            foreach (var obj in searcherTotal.Get()) {
                double totalBytes = Convert.ToDouble(obj["TotalPhysicalMemory"]);
                metrics.TotalGb = Math.Round(totalBytes / (1024.0 * 1024.0 * 1024.0), 2);
            }

            using var searcherFree = new ManagementObjectSearcher("SELECT FreePhysicalMemory FROM Win32_OperatingSystem");
            foreach (var obj in searcherFree.Get()) {
                double freeKb = Convert.ToDouble(obj["FreePhysicalMemory"]);
                metrics.FreeGb = Math.Round(freeKb / (1024.0 * 1024.0), 2);
            }
        } catch { }
    }

    private static void GetLinuxRam(RamMetrics metrics) {
        try {
            string[] lines = File.ReadAllLines("/proc/meminfo");
            var totalParts = lines[0].Split(" ", StringSplitOptions.RemoveEmptyEntries);
            var freeParts = lines[1].Split(" ", StringSplitOptions.RemoveEmptyEntries);

            metrics.TotalGb = Math.Round(double.Parse(totalParts[1]) / (1024.0 * 1024.0), 2);
            metrics.FreeGb = Math.Round(double.Parse(freeParts[1]) / (1024.0 * 1024.0), 2);
        } catch { }
    }

    private static void GetMacRam(RamMetrics metrics) {
        try {
            var total = BashUtils.GetBashCommandOutput("sysctl -n hw.memsize");
            metrics.TotalGb = Math.Round(double.Parse(total) / (1024.0 * 1024.0 * 1024.0), 2);
            
            metrics.FreeGb = 0; 
        } catch { }
    }
}