/******************************************************************************/
/* SlunkCrypt, by LoRd_MuldeR <MuldeR2@GMX.de>                                */
/* This work has been released under the CC0 1.0 Universal license!           */
/******************************************************************************/

using System;
using System.ComponentModel;
using com.muldersoft.slunkcrypt.gui.utils.cpu;

namespace com.muldersoft.slunkcrypt.gui.process
{
    struct CPUFeatures
    {
        public enum CPUArch
        {
            [Description("x86")]    x86 = 0x1,
            [Description("x64")]    x64 = 0x2,
            [Description("ARM64")]  a64 = 0x3
        }
 
        public readonly CPUArch cpuArch;
        public readonly bool hasSSE2, hasAVX2;

        private static readonly Lazy<CPUFeatures> cpuFeatures = new Lazy<CPUFeatures>(DetectFeatures);

        public static CPUFeatures Features
        {
            get { return cpuFeatures.Value; }
        }

        public CPUFeatures(CPUArch cpuArch, bool hasSSE2, bool hasAVX2)
        {
            this.cpuArch = cpuArch;
            this.hasSSE2 = hasSSE2;
            this.hasAVX2 = hasAVX2;
        }

        private static CPUFeatures DetectFeatures()
        {
            try
            {
                CPUArchitecture cpuArchitecture = CPU.Architecture;
                switch(cpuArchitecture)
                {
                    case CPUArchitecture.CPU_ARCH_X86:
                        return new CPUFeatures(CPUArch.x86, CPU.Capabilities.HasFlag(CPUCapabilities.CPU_SSE2), CPU.Capabilities.HasFlag(CPUCapabilities.CPU_AVX2));
                    case CPUArchitecture.CPU_ARCH_X64:
                        return new CPUFeatures(CPUArch.x64, CPU.Capabilities.HasFlag(CPUCapabilities.CPU_SSE2), CPU.Capabilities.HasFlag(CPUCapabilities.CPU_AVX2));
                    case CPUArchitecture.CPU_ARCH_A64:
                        return new CPUFeatures(CPUArch.a64, false, false);
                }
            }
            catch { }
            return new CPUFeatures(CPUArch.x86, false, false);
        }
    }
}
