using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using TerraFX.Interop.Windows;

// ReSharper disable InconsistentNaming
// ReSharper disable IdentifierTypo
// ReSharper disable CommentTypo
#pragma warning disable 649

namespace Robust.Shared.Utility
{
    internal static unsafe class ProcessExt
    {
        // THIS ENTIRE METHOD EXISTS PURELY OUT OF SPITE FOR MICROSOFT.
        // NOT TO SAVE 0.3% CPU USAGE ON WINDOWS. NAH.
        // TO SPITE MICROSOFT.
        // WHAT ABOUT THE 2.2% CPU USAGE IN CONSOLE.KEYAVAILABLE? WHAT ABOUT THAT WHATABOUTISM HUH???
        // I WANTED TO GO TO BED NOW IT'S 4:20 AM (BASED) GOD DAMNIT.
        // AS A RESULT, EVERYTHING HERE WILL BE WRITTEN IN *FUCKING* CAPS.
        [MethodImpl(MethodImplOptions.NoInlining)]
        public static long GetPrivateMemorySize64NotSlowHolyFuckingShitMicrosoft(this Process process)
        {
            if (!OperatingSystem.IsWindows())
                // IT'S NOT SLOW ON LINUX, *LUCKILY*.
                // WELL I DIDN'T PROFILE IT BUT THEY DON'T DO A STUPID SEARCH OVER EVERY PROCESS.
                // IT USES PROCFS, IF YOU'RE CURIOUS.
                return process.PrivateMemorySize64;

            //
            // GLASS TOLD ME TO PUT A TL;DR IN SO TL;DR
            // PROCESS.PRIVATEMEMORYSIZE64 (AND A BUNCH OF OTHERS) ARE SLOW AS BALLS (2+ms for me).
            // THIS ISN'T.
            //
            // AS IT *FUCKING* TURNS OUT.
            // *MANY* OF THE FIELDS ON PROCESS (THE CLASS, YOU KNOW THE ONE THIS METHOD IS AN EXTENSION FOR) HAVE TO FETCH A "PROCESS INFO".
            // HOW DO YOU FETCH A PROCESS INFO ON WINDOWS? OH YEAH YOU CALL NTQUERYSYSTEMINFORMATION APPARENTLY.
            // OH WAIT. THAT RETURNS INFO FOR *EVERY* PROCESS ON THE FUCKING SYSTEM.
            // SO YES. IF YOU LOOK UP PROCESS.PRIVATEMEMORYSIZE64, IT HAS TO SEARCH THROUGH *EVERY PROCESS ON THE FUCKING SYSTEM* TO FIND THE PROCESS IT'S LOOKING FOR.
            // THIS TAKES MORE THAN 2 FUCKING MILLISECONDS PER LOOKUP ON MY SYSTEM.
            // IF THE TITLE BAR ON THE CONSOLE WAS UPDATED EVERY TICK INSTEAD OF ONCE PER FRAME, THIS WOULD LITERALLY BE MOST OF THE IDLE SERVER CPU USAGE.
            // ***ARE YOU FUCKING KIDDING ME ????***
            // OH YEAH, NTQUERYSYSTEMINFORMATION IS DOCUMENTED AS AN UNSTABLE API THAT CAN CHANGE AT ANY TIME, APPARENTLY.
            // .NET FEELS IT'S FINE TO USE THAT (YEAH GUESS THEY'RE NEVER REMOVING IT FROM WINDOWS LMAO)
            // ARE YOU FUCKING TELLING ME THE .NET TEAM COULDN'T HAVE WALKED TO THE OTHER SIDE OF THE OFFICE AND TOLD THE KERNEL TEAM TO ADD A VERSION OF NTQUERYSYSTEMINFORMATION THAT FETCHES INFO FOR A SINGLE PROCESS?
            // THEY THOUGHT THIS SHIT WAS FUCKING ACCEPTABLE?
            // JESUS FUCKING CHRIST.
            // ANYWAYS, THIS EXTENSION METHOD USES GETPROCESSMEMORYINFO() INSTEAD BECAUSE THAT'S PROBABLY NOT FUCKING MORONIC.
            //

            PROCESS_MEMORY_COUNTERS_EX counters;

            if (Windows.GetProcessMemoryInfo(
                    (HANDLE)process.Handle,
                    (PROCESS_MEMORY_COUNTERS*)(&counters),
                    (uint)sizeof(PROCESS_MEMORY_COUNTERS_EX)) == 0)
                return 0;

            var count = counters.PrivateUsage;

            return (long)count;
        }
    }
}
