using System.Runtime.InteropServices;

namespace Pilz.Runtime;

public static class RuntimeInformationsEx
{
    private static OSType? osType;
    private static OSType? osTypeReal;

    public static OSType OSType => osType ??= GetOSType();

    public static OSType RealOSType => osTypeReal ??= GetRealOSType();

    public static OSType GetOSType()
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            return OSType.Windows;

        if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            return OSType.Linux;

        if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
            return OSType.OSX;

        return OSType.Unknown;
    }

    public static OSType GetRealOSType()
    {
        var windir = Environment.GetEnvironmentVariable("windir");
        const string ostypeDirWine = @"Z:\proc\sys\kernel\ostype";
        const string ostypeDirNative = "/proc/sys/kernel/ostype";
        const string systemVersionWine = @"Z:\System\Library\CoreServices\SystemVersion.plist";
        const string systemVersionNative = "/System/Library/CoreServices/SystemVersion.plist";

        // Linux using wine
        if (File.Exists(ostypeDirWine))
        {
            var osTypeString = File.ReadAllText(ostypeDirWine);
            if (osTypeString.StartsWith("Linux", StringComparison.OrdinalIgnoreCase))
                // Note: Android gets here too
                return OSType.Linux;
            else
                return OSType.Unknown;
        }

        // Linux native
        else if (File.Exists(ostypeDirNative))
        {
            var osTypeString = File.ReadAllText(ostypeDirNative);
            if (osTypeString.StartsWith("Linux", StringComparison.OrdinalIgnoreCase))
                // Note: Android gets here too
                return OSType.Linux;
            else
                return OSType.Unknown;
        }

        // OSX using wine
        else if (File.Exists(systemVersionWine))
            // Note: iOS gets here too
            return OSType.OSX;

        // OSX native
        else if (File.Exists(systemVersionNative))
            // Note: iOS gets here too
            return OSType.OSX;

        // Windows
        else if (!string.IsNullOrEmpty(windir) && Directory.Exists(windir) && Path.DirectorySeparatorChar == '\\')
            return OSType.Windows;

        return OSType.Unknown;
    }

    public static bool IsOSPlatform(OSType os, bool checkRealOS)
    {
        return (checkRealOS ? RealOSType : OSType) == os;
    }
}