#pragma once

#include "Common.h"
#include "System/Object.h"
#include "System/String.h"
#include "System/SmartPointer.h"
#include "System/Action.h"
#include "System/Collections/Generic/List.h"
#include "System/Diagnostics/ProcessStreamOptions.h"

namespace DotNetDupe {
    namespace System {
        namespace Diagnostics {

            class ProcessStreamer;

            struct MemoryInfo {
                double dMemoryUsagePercent;
                unsigned long long uMemoryTotalBytes;
                unsigned long long uMemoryUsedBytes;
                long long lPrivateBytes;
                long long lPhysicalMemoryBytes; // Working Set

                MemoryInfo()
                    : dMemoryUsagePercent(0.0),
                      uMemoryTotalBytes(0ULL),
                      uMemoryUsedBytes(0ULL),
                      lPrivateBytes(-1),
                      lPhysicalMemoryBytes(-1) {}
            };

            struct DiskInfo {
                long long lDiskReadBytes;
                long long lDiskWriteBytes;

                DiskInfo() : lDiskReadBytes(-1), lDiskWriteBytes(-1) {}
            };

            struct NetworkUsageInfo {
                long long lNetworkReadBytes;
                long long lNetworkWriteBytes;

                NetworkUsageInfo() : lNetworkReadBytes(-1), lNetworkWriteBytes(-1) {}
            };

            struct NetworkConnectionInfo {
                String sLocalAddress;
                int iLocalPort;
                String sRemoteAddress;
                int iRemotePort;
                String sState; // e.g. "ESTABLISHED", "LISTEN", "TIME_WAIT", etc.

                NetworkConnectionInfo() : iLocalPort(0), iRemotePort(0) {}
            };

            struct ProcessNetworkConnectionInfo {
                Collections::Generic::List<int> lstOpenPorts;
                Collections::Generic::List<NetworkConnectionInfo> lstConnections;
                bool bHasEstablishedInboundConnection;

                ProcessNetworkConnectionInfo() : bHasEstablishedInboundConnection(false) {}
            };

            struct ProcessInfo {
                int iProcessId;
                int iSessionId;
                String sName;
                String sPath;
                String sCommandLine;
                double dCpuUsagePercent;
                MemoryInfo memory;
                DiskInfo disk;
                NetworkUsageInfo network;
                Collections::Generic::List<int> lstOpenPorts;
                Collections::Generic::List<NetworkConnectionInfo> lstConnections;
                bool bHasEstablishedConnection;

                ProcessInfo()
                    : iProcessId(0),
                      iSessionId(0),
                      dCpuUsagePercent(0.0),
                      bHasEstablishedConnection(false) {}
            };

            struct ServiceInfo {
                String sServiceName;
                String sDisplayName;
                String sStatus; // e.g. "Running", "Stopped", "Paused", "StartPending", etc.
                String sStartType; // e.g. "Automatic", "Manual", "Disabled", etc.
                int iProcessId;

                ServiceInfo() : iProcessId(0) {}
            };

            class SystemMetrics : public Object {
            public:
                DOTNETDUPE_API SystemMetrics();
                DOTNETDUPE_API virtual ~SystemMetrics();

                // System-wide metrics
                DOTNETDUPE_API static MemoryInfo GetSystemMemoryUsage();
                DOTNETDUPE_API static double GetSystemCpuUsage();
                DOTNETDUPE_API static DiskInfo GetSystemDiskUsage();
                DOTNETDUPE_API static double GetSystemNetworkUsage();

                // Process-specific metrics (by process name, internally using handle-based APIs)
                DOTNETDUPE_API static String GetProcessCommandLine(const String& sProcessName);
                DOTNETDUPE_API static MemoryInfo GetProcessMemoryUsage(const String& sProcessName);
                DOTNETDUPE_API static DiskInfo GetProcessDiskUsage(const String& sProcessName);
                DOTNETDUPE_API static NetworkUsageInfo GetProcessNetworkUsage(const String& sProcessName);
                DOTNETDUPE_API static Collections::Generic::List<int> GetProcessNetworkPort(const String& sProcessName);
                DOTNETDUPE_API static ProcessNetworkConnectionInfo GetProcessNetworkInfo(const String& sProcessName);

                // Process-specific metrics by PID
                DOTNETDUPE_API static Collections::Generic::List<int> GetProcessNetworkPort(int iProcessId);
                DOTNETDUPE_API static ProcessNetworkConnectionInfo GetProcessNetworkInfo(int iProcessId);
                DOTNETDUPE_API static void EnrichProcessInfo(ProcessInfo& proc, bool bIncludeNetwork = true);

                // Process list & enumeration APIs
                DOTNETDUPE_API static Collections::Generic::List<ProcessInfo> GetAllProcesses(int iSessionId = -1);

                // Progressive Streaming APIs
                DOTNETDUPE_API static SmartPointer<ProcessStreamer> CreateProcessStreamer(const ProcessStreamOptions& options = ProcessStreamOptions());
                DOTNETDUPE_API static void EnumerateProcessesAsync(const Action<const ProcessInfo&>& fnOnProcess, const Action<>& fnOnComplete = nullptr);

                // Service enumeration API
                DOTNETDUPE_API static Collections::Generic::List<ServiceInfo> GetAllServices();

            private:
#if defined(_WIN32)
                static void* OpenProcessByName(const String& sProcessName, unsigned long dwDesiredAccess, int& iOutProcessId);
                static String ReadProcessCommandLineHandle(void* hProc);
                static MemoryInfo ReadProcessMemoryHandle(void* hProc);
                static DiskInfo ReadProcessDiskHandle(void* hProc, const String& sProcessName);
                static NetworkUsageInfo ReadProcessNetworkHandle(void* hProc, const String& sProcessName);
                static Collections::Generic::List<int> ReadProcessNetworkPortInternal(int iProcessId);
                static ProcessNetworkConnectionInfo ReadProcessNetworkInfoInternal(int iProcessId);
                static void PopulateProcessInfo(void* pEntry32, ProcessInfo& proc);
#else
                static int FindPidByName(const String& sProcessName);
                static MemoryInfo ReadLinuxProcessMemory(int iPid);
                static DiskInfo ReadLinuxProcessDisk(int iPid);
                static NetworkUsageInfo ReadLinuxProcessNetwork(int iPid);
                static Collections::Generic::List<int> ReadLinuxProcessPorts(int iPid);
                static ProcessNetworkConnectionInfo ReadLinuxProcessNetworkInfo(int iPid);
                static void PopulateLinuxProc(const std::string& dname, ProcessInfo& proc);
#endif
            };

        }
    }
}

Generated by OpenCppCoverage (Version: 0.9.9.0)