using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace Common
{
    public static class MyDes
    {
        public const string AuthorizationCode = "D7CD0C3660F6A658C9668233516A5397";
        private static log4net.ILog logger = log4net.LogManager.GetLogger(typeof(MyDes));
        private static System.Security.Cryptography.DES mydes = new DESCryptoServiceProvider();
        private static string m_key = "szblw_license";
        private static string m_iv = "szblw_license";
        private static object _lock = new object();

        private static byte[] GetLegalKey()
        {
            string sTemp = m_key;
            mydes.GenerateKey();
            byte[] bytTemp = mydes.Key;
            int KeyLength = bytTemp.Length;
            if (sTemp.Length > KeyLength)
                sTemp = sTemp.Substring(0, KeyLength);
            else if (sTemp.Length < KeyLength)
                sTemp = sTemp.PadRight(KeyLength, ' ');
            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        private static byte[] GetLegalIV()
        {
            string sTemp = m_iv;
            mydes.GenerateIV();
            byte[] bytTemp = mydes.IV;
            int IVLength = bytTemp.Length;
            if (sTemp.Length > IVLength)
                sTemp = sTemp.Substring(0, IVLength);
            else if (sTemp.Length < IVLength)
                sTemp = sTemp.PadRight(IVLength, ' ');
            return ASCIIEncoding.ASCII.GetBytes(sTemp);
        }

        #region 解密 License

        /// <summary>
        /// 解密文件
        /// </summary>
        /// <param name="inFileName"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool DecodeFromFile(string inFileName, ref string result)
        {
            return Decode(File.ReadAllText(inFileName), ref result);
        }

        /// <summary>
        /// 解密文件
        /// </summary>
        /// <param name="inFileName"></param>
        /// <param name="key"></param>
        /// <param name="iv"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool DecodeFromStream(Stream stream, ref string result)
        {
            using (StreamReader reader = new StreamReader(stream))
            {
                return Decode(reader.ReadToEnd(), ref result);
            }
        }

        /// <summary>
        /// 解密文件
        /// </summary>
        /// <param name="base64License"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool Decode(string base64License, ref string result)
        {
            try
            {
                mydes.IV = GetLegalIV();
                mydes.Key = GetLegalKey();
                byte[] btFile = Convert.FromBase64String(base64License);
                ICryptoTransform encrypto = mydes.CreateDecryptor();
                using (MemoryStream mStream = new MemoryStream())
                {
                    using (CryptoStream encStream = new CryptoStream(mStream, encrypto, CryptoStreamMode.Write))
                    {
                        encStream.Write(btFile, 0, btFile.Length);
                        encStream.FlushFinalBlock();
                        result = Encoding.UTF8.GetString(mStream.ToArray());
                    }
                }
            }
            catch (Exception ex)
            {
                result = "解密文件失败！原因：" + ex.Message;
                if (logger.IsErrorEnabled)
                {
                    logger.Error(result, ex);
                }
                return false;
            }
            return true;
        }

        #endregion

        #region 验证License

        /// <summary>
        /// 每次登录验证，验证成功时修改License文件的最后写入时间
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool Validate(ref string result)
        {
            string file = GetLicensePath();
            if (!System.IO.File.Exists(file))
            {
                result = "授权文件不存在！";
                return false;
            }
            string strLicense = "";
            if (!DecodeFromFile(file, ref strLicense))
            {
                result = "无效的授权文件！";
                return false;
            }
            bool ret = Validate(strLicense, ref result);
            if (ret)
            {
                File.SetLastWriteTime(file, DateTime.Now);
            }
            return ret;
        }

        /// <summary>
        /// 导入授权文件验证
        /// </summary>
        /// <param name="licenseStream"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool ImportValidate(Stream licenseStream, ref string result)
        {
            string strLicense = "";
            if (!Common.MyDes.DecodeFromStream(licenseStream, ref strLicense))
            {
                result = "无效的授权文件！";
                return false;
            }

            return Validate(strLicense, ref result);
        }

        /// <summary>
        /// 验证 License文件
        /// </summary>
        /// <param name="strLicense"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public static bool Validate(string strLicense, ref string result)
        {
            License license = ReadLicense(strLicense);
            if (license == null)
            {
                result = "无效的授权文件！";
                return false;
            }
            if (license.SystemTypeID != 0)
            {
                result = "授权文件不匹配本系统！";
                return false;
            }
            //判断授权文件上的机器码是否符合当前电脑的机器码，如机器码是12个0，不做校验
            if (license.MAC != Tools.GetMachineCode())
            {
                result = "机器码与授权文件不匹配！";
                return false;
            }
            DateTime now = GetServerDate();
            if (now < license.StartDate || now > license.EndDate)
            {
                result = "授权到期！";
                return false;
            }
            result = "验证成功！";
            return true;
        }

        private static DateTime GetServerDate()
        {
            DateTime nowDate = DateTime.Now.Date;
            string file = GetLicensePath();
            if (!File.Exists(file))
            {
                return nowDate;
            }
            DateTime fileTime = File.GetLastWriteTime(file);
            if (fileTime > DateTime.Now)
            {
                return fileTime.Date;
            }
            return nowDate;
        }

        #endregion

        public static License GetLicense()
        {
            string result = "";
            if (DecodeFromFile(GetLicensePath(), ref result))
            {
                return ReadLicense(result);
            }
            return null;
        }

        public static string GetLicensePath()
        {
            return Tools.GetApplicationPath() + @"License\blw-t3s.lic";
        }

        public static License ReadLicense(string strLicense)
        {
            try
            {
                lock (_lock)
                {
                    if (strLicense.Contains("<?"))
                    {
                        strLicense = strLicense.Substring(strLicense.IndexOf('>') + 1);//去掉xml header
                    }
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(strLicense);
                    XmlNode data = doc.DocumentElement.GetElementsByTagName("data")[0];
                    License license = new License()
                    {
                        ID = data.Attributes["id"].Value,
                        CustomerID = data.Attributes["customerid"].Value,
                        Customer = data.Attributes["customer"].Value,
                        SN = data.Attributes["sn"].Value,
                        Key = data.Attributes["key"].Value,
                        MAC = data.Attributes["mac"].Value,
                        Limit = Convert.ToInt32(data.Attributes["limit"].Value),
                        StartDate = Convert.ToDateTime(data.Attributes["start"].Value),
                        EndDate = Convert.ToDateTime(data.Attributes["end"].Value),
                        SystemTypeID = Convert.ToInt32(data.Attributes["systemtypeid"].Value)
                    };
                    data = null;
                    doc = null;
                    GC.Collect();
                    return license;
                }
            }
            catch (Exception ex)
            {
                logger.Error(string.Format("读取license失败：{0}", ex.ToString()));
                return null;
            }
        }
    }

    public class License
    {
        public string ID { get; set; }
        public string CustomerID { get; set; }
        public string Customer { get; set; }
        public string SN { get; set; }
        public string Key { get; set; }
        public string MAC { get; set; }
        public int Limit { get; set; }
        public DateTime StartDate { get; set; }
        public DateTime EndDate { get; set; }
        public int SystemTypeID { get; set; }
    }
}
