using Microsoft.Win32;
using System;
using System.IO;
using System.Management;
using System.Security.Cryptography;
using System.Text;

namespace SWRIS.Core
{
    /// <summary>
    /// 软件授权类
    /// </summary>
    public class SoftAuth
    {
        /// <summary>
        /// 获取本计算机唯一的机器码（长度取前12个字符）
        /// </summary>
        /// <returns>字符串形式的机器码</returns>
        public static string GetMachineCode()
        {
            string unique = "";
            //bios名称
            unique += HWID.BIOS + "|";
            //cpu信息
            unique += HWID.CPU + "|";
            //主板信息
            unique += HWID.BaseBoard + "|";

            //获取SMBIOS的Id
            ManagementClass cimobject3 = new ManagementClass("Win32_ComputerSystemProduct");
            ManagementObjectCollection moc3 = cimobject3.GetInstances();
            foreach (ManagementObject mo in moc3)
            {
                unique += (string)mo.Properties["UUID"].Value;
                break;
            }
            SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
            var md5 = ByteToHexString(SHA1.ComputeHash(Encoding.Unicode.GetBytes(unique)), (char)0, 0);
            return md5.Substring(0, 12);
        }
        /// <summary>
        /// 获取本机激活码
        /// </summary>
        /// <returns></returns>
        public static string GetFinalCode()
        {
            return MD5Encrypt(GetMachineCode()).Substring(0, 16);
        }
        /// <summary>
        /// 判断是否已激活
        /// </summary>
        /// <returns></returns>
        public static bool IsAuthorizeSuccess()
        {
            if (GetFinalCode() == ReadRegistry())
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 验证激活码是否正确
        /// </summary>
        /// <param name="finalCode">用户输入的注册码</param>
        /// <returns></returns>
        public static bool CheckFinalCode(string finalCode)
        {
            if (GetFinalCode() == finalCode.Trim().ToUpper())
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        /// <summary>
        /// 字节数据转化成16进制表示的字符串
        /// </summary>
        /// <param name="InBytes">字节数组</param>
        /// <param name="segment">分割符</param>
        /// <param name="newLineCount">每隔指定数量的时候进行换行</param>
        /// <returns>返回的字符串</returns>
        /// <example>
        /// </example>
        private static string ByteToHexString(byte[] InBytes, char segment, int newLineCount)
        {
            if (InBytes == null) return string.Empty;
            StringBuilder sb = new StringBuilder();
            long tick = 0;
            foreach (byte InByte in InBytes)
            {
                if (segment == 0) sb.Append(string.Format("{0:X2}", InByte));
                else sb.Append(string.Format("{0:X2}{1}", InByte, segment));

                tick++;
                if (newLineCount > 0 && tick >= newLineCount)
                {
                    sb.Append(Environment.NewLine);
                    tick = 0;
                }
            }

            if (segment != 0 && sb.Length > 1 && sb[sb.Length - 1] == segment)
            {
                sb.Remove(sb.Length - 1, 1);
            }
            return sb.ToString();
        }
        /// <summary>
        /// 加密数据，采用DES对称加密的方式
        /// </summary>
        /// <param name="pToEncrypt">待加密的数据</param>
        /// <param name="password">密钥，长度为8，英文或数字</param>
        /// <returns>加密后的数据</returns>
        public static string MD5Encrypt(string pToEncrypt, string password = "!234Qwer")
        {
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] inputByteArray = Encoding.Default.GetBytes(pToEncrypt);
            des.Key = Encoding.ASCII.GetBytes(password);
            des.IV = Encoding.ASCII.GetBytes(password);
            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            StringBuilder ret = new StringBuilder();
            foreach (byte b in ms.ToArray())
            {
                ret.AppendFormat("{0:X2}", b);
            }
            ret.ToString();
            return ret.ToString();
        }
        /// <summary>
        /// 激活码写入注册表
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static bool WriteRegistry(string code)
        {
            try
            {
                RegistryKey regkeySetKey = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\HenDai\SoftAuthorize\Common", true);
                regkeySetKey.SetValue("Code", code);
                regkeySetKey.SetValue("Time", DateTime.Now.ToString());
                return true;
            }
            catch { return false; }
        }
        /// <summary>
        /// 读取注册表内激活码
        /// </summary>
        /// <returns></returns>
        public static string ReadRegistry()
        {
            try
            {
                RegistryKey regkey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\HenDai\SoftAuthorize\Common");
                return regkey?.GetValue("Code", string.Empty).ToString();
            }
            catch
            {
                return string.Empty;
            }
        }
        private class HWID
        {
            public static string BIOS { get { return GetWMIIdent("Win32_BIOS", "Manufacturer", "SerialNumber", "SMBIOSBIOSVersion"); } }
            public static string CPU { get { return GetWMIIdent("Win32_Processor", "ProcessorId"); } }
            public static string HDD { get { return GetWMIIdent("Win32_DiskDrive", "Model"); } }
            public static string BaseBoard { get { return GetWMIIdent("Win32_BaseBoard", "SerialNumber"); } }
        }
        private static string GetWMIIdent(string Class, string Property)
        {
            var ident = "";
            var objCol = new ManagementClass(Class).GetInstances();
            foreach (var obj in objCol)
            {
                if ((ident = obj.GetPropertyValue(Property) as string) != "")
                    break;
            }
            return ident;
        }
        private static string GetWMIIdent(string Class, params string[] Propertys)
        {
            var ident = "";
            Array.ForEach(Propertys, prop => ident += GetWMIIdent(Class, prop) + " ");
            return ident;
        }
    }
}
