//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;
#if WIN32
using Microsoft.Win32;
#endif // WIN32

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
/// <summary>
/// </summary>
public static partial class HOperatingSystem {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static readonly OperatingSystem
   Windows81orServer2012R2 =
      new OperatingSystem( PlatformID.Win32NT, new Version(6,3) ),
   Windows8orServer2012 =
      new OperatingSystem( PlatformID.Win32NT, new Version(6,2) ),
   Windows7orServer2008R2 =
      new OperatingSystem( PlatformID.Win32NT, new Version(6,1) ),
   WindowsVistaOrServer2008 =
      new OperatingSystem( PlatformID.Win32NT, new Version(6,0) ),
   WindowsXP64BitOrServer2003orR2 =
      new OperatingSystem( PlatformID.Win32NT, new Version(5,2) ),
   WindowsXP =
      new OperatingSystem( PlatformID.Win32NT, new Version(5,1) ),
   Windows2000 =
      new OperatingSystem( PlatformID.Win32NT, new Version(5,0) );

//==================================================================================================

public static bool IsWindows => IsWindowsOS( Environment.OSVersion );

//--------------------------------------------------------------------------------------------------
#if WIN32
public static bool IsProbablyWindows10orLater
{
   get
   {
      lock ( _Windows10orLaterSyncObject_ )
      {
         if ( !_IsProbablyWindows10orLater_.HasValue )
            if ( IsWindows8orLater )
               try
               {
                  _IsProbablyWindows10orLater_ = Registry.GetValue(
                     @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion",
                     "CurrentMajorVersionNumber", null ) != null;
               }
               catch
               {
                  _IsProbablyWindows10orLater_ = false;
               }
            else
               _IsProbablyWindows10orLater_ = false;
         return
            _IsProbablyWindows10orLater_.Value;
      }
   }
}
#endif // WIN32
//--------------------------------------------------------------------------------------------------

public static bool IsWindows81orLater =>
   IsWindows81orLaterEx( Environment.OSVersion );

public static bool IsWindows8orLater =>
   IsWindows8orLaterEx( Environment.OSVersion );

public static bool IsWindows7orLater =>
   IsWindows7orLaterEx( Environment.OSVersion );

public static bool IsWindowsVistaOrLater =>
   IsWindowsVistaOrLaterEx( Environment.OSVersion );

public static bool WindowsHP64BitOrLater =>
   IsWindowsHP64BitOrLaterEx( Environment.OSVersion );

public static bool IsWindowsHPOrLater =>
   IsWindowsHPOrLaterEx( Environment.OSVersion );

public static bool IsWindows2000orLater =>
   IsWindows2000orLaterEx( Environment.OSVersion );

//==================================================================================================

public static bool IsWindowsOS(OperatingSystem system) =>
   system.Platform == PlatformID.Win32NT;

//--------------------------------------------------------------------------------------------------

public static bool IsWindows81orLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( Windows81orServer2012R2 );

public static bool IsWindows8orLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( Windows8orServer2012 );

public static bool IsWindows7orLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( Windows7orServer2008R2 );

public static bool IsWindowsVistaOrLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( WindowsVistaOrServer2008 );

public static bool IsWindowsHP64BitOrLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( WindowsXP64BitOrServer2003orR2 );

public static bool IsWindowsHPOrLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( WindowsXP );

public static bool IsWindows2000orLaterEx(OperatingSystem system) =>
   CheckOperatingSystem( Windows2000 );

//==================================================================================================

public static bool CheckOperatingSystem(OperatingSystem requiredMinimalOS)
{
   HArgChecking.VerifyNotNull( requiredMinimalOS );
   var system = Environment.OSVersion;
   bool stdCheckResult =
      system.Platform == requiredMinimalOS.Platform &&
      system.Version >= requiredMinimalOS.Version;
   if ( stdCheckResult )
      return true;
#if WIN32
   if ( IsProbablyWindows10orLater )
      return true;
#endif // WIN32
   return false;
}

//==================================================================================================

public static string GetNameOrVersionString(OperatingSystem system)
{
   HArgChecking.VerifyNotNull( system );

   if (system.Platform == PlatformID.Win32NT)
   {
      if (system == Windows81orServer2012R2)
         return "Windows 8.1 / Windows Server 2012 R2";
      if (system == Windows8orServer2012)
         return "Windows 8 / Windows Server 2012";
      if (system == Windows7orServer2008R2)
         return "Windows 7 / Windows Server 2008 R2";
      if (system == WindowsVistaOrServer2008)
         return "Windows Vista / Windows Server 2008";
      if (system == WindowsXP64BitOrServer2003orR2)
         return "Windows HP 64 Bit Edition / Windows Server 2003 / Windows Server 2003 R2";
      if (system == WindowsXP)
         return "Windows XP";
      if (system == Windows2000)
         return "Windows 2000";
   }
   return system.VersionString;
}

//==================================================================================================

static HOperatingSystem()
{
   CommonHelpers_Core.Access();
}

//==================================================================================================

static object
   _Windows10orLaterSyncObject_ = new object();
#if WIN32
static bool?
   _IsProbablyWindows10orLater_;
#endif // WIN32

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HOperatingSystem
//**************************************************************************************************

} // CommonHelpers (.WASM)
