using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace Siger.Middlelayer.Common.Helpers
{
    public class HMACHelper
    {
        public const string JavaKeyGenCode = "6jL7cfs+M66S+lS7IcK1xzSZsJiAp4iAkHEH0yAoxYg=";

        public static string CreateToBase(string message, string secret)
        {
            secret = secret ?? "";
            var encoding = new ASCIIEncoding();
            var keyByte = encoding.GetBytes(secret);
            var messageBytes = encoding.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                var hashmessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashmessage);
            }
        }

        public static string Encrypt(string message, string secret)
        {
            secret = secret ?? "";
            var encoding = new UTF8Encoding();
            var keyByte = encoding.GetBytes(secret);
            var messageBytes = encoding.GetBytes(message);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                var hashmessage = hmacsha256.ComputeHash(messageBytes);
                var builder = new StringBuilder();
                for (var i = 0; i < hashmessage.Length; i++)
                {
                    builder.Append(hashmessage[i].ToString("x2"));
                }

                var b = Encoding.Default.GetBytes(builder.ToString());
                return Convert.ToBase64String(b);
            }
        }

        public static bool verificateRequestParams(NameValueCollection nvc, String accessKey, int encryptLength = 128)
        {
            //解析出url内容
            SortedDictionary<string, string> sortDic = new SortedDictionary<string, string>();
            foreach (string eachkey in nvc.Keys)
            {
                sortDic.Add(eachkey, nvc[eachkey]);
            }
            String timeStamp = nvc["timeStamp"];
            String authToken = nvc["authToken"].Replace(" ", "+");
            //对剩下的参数进行排序，拼接成加密内容
            sortDic.Remove("authToken");
            string reqParams = string.Join("&", sortDic.Select(a => a.Key + "=" + a.Value));  // a=1&b=2&c=3
            //修正消息体,去除第一个参数前面的&
            String key = accessKey + timeStamp;
            String signature = null;
            try
            {
                signature = generateResponseBodySignature(key, reqParams);
            }
            catch
            {
                // TODO Auto-generated catch block
            }
            if (authToken == null) { return false; }
            return authToken.Equals(signature);
        }

        /// <summary>
        /// 生成签名
        /// </summary>
        /// <param name="key"></param>
        /// <param name="body"></param>
        /// <returns></returns>
        public static String generateResponseBodySignature(String key, String body)
        {
            return HMACSHA256Encrypt_Base64(body, key, Encoding.UTF8);
        }

        public static string HMACSHA256Encrypt_Base64(string input, string key, Encoding encoding)
        {
            key = key ?? "";
            byte[] keyByte = encoding.GetBytes(key);
            byte[] messageBytes = encoding.GetBytes(input);
            using (var hmacsha256 = new HMACSHA256(keyByte))
            {
                byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
                return Convert.ToBase64String(hashmessage);
            }
        }

        /// <summary>
        /// 用户名和密码进行加密
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="str">原文</param>
        /// <param name="encryptLength"></param>
        /// <returns></returns>
        public static String generateSaaSUsernameOrPwd(String key, String str, int encryptLength)
        {
            string iv = Guid.NewGuid().ToString().Replace("-", "").Substring(0, 16);
            String afterEncryptStr = "";
            try
            {
                afterEncryptStr = AESEncrypt(str, JavaKeyGenCode, iv, encryptLength);
            }
            catch
            {
                //TODO:异常处理
            }
            return iv + afterEncryptStr;
        }

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="text"></param>
        /// <param name="password"></param>
        /// <param name="iv"></param>
        /// <param name="keySize"></param>
        /// <returns></returns>
        public static string AESEncrypt(string text, string password, string iv, int keySize = 256)
        {
            //password = "KQsezTW8AzcLshiEo/WcsGrgkUGEqTiInXMnPM2AJto="; //传过来的密码经过java的keggen 代码产生出来
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = keySize;
            byte[] pwdBytes = Convert.FromBase64String(password);
            rijndaelCipher.Key = pwdBytes;
            byte[] ivBytes = System.Text.Encoding.UTF8.GetBytes(iv);
            rijndaelCipher.IV = ivBytes;
            ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
            byte[] plainText = Encoding.UTF8.GetBytes(text);
            byte[] cipherBytes = transform.TransformFinalBlock(plainText, 0, plainText.Length);
            return Convert.ToBase64String(cipherBytes);
        }

        /// <summary>
        /// 解密手机号码或邮箱
        /// </summary>
        /// <param name="key">密钥</param>
        /// <param name="str">密文</param>
        /// <param name="encryptLength">加密长度</param>
        /// <returns>解密结果</returns>
        public static String decryptMobilePhoneOrEMail(String key, String str, int encryptLength = 256)
        {
            if (null != str && str.Length > 16)
            {
                String iv = str.Substring(0, 16);
                String encryptStr = str.Substring(16);
                String result = null;
                try
                {
                    result = AESDecrypt(encryptStr, JavaKeyGenCode, iv, encryptLength);
                }
                catch
                {

                }
                return result;
            }
            return null;
        }

        public static string AESDecrypt(string text, string password, string iv, int keySize = 256)
        {
            //password = "KQsezTW8AzcLshiEo/WcsGrgkUGEqTiInXMnPM2AJto="; //传过来的密码经过java的keggen 代码产生出来
            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;
            rijndaelCipher.KeySize = keySize;
            //rijndaelCipher.BlockSize = keySize; //添加这一句坏事
            byte[] encryptedData = Convert.FromBase64String(text);
            byte[] pwdBytes = Convert.FromBase64String(password);
            rijndaelCipher.Key = pwdBytes;
            byte[] ivBytes = System.Text.Encoding.UTF8.GetBytes(iv);
            rijndaelCipher.IV = ivBytes;
            ICryptoTransform transform = rijndaelCipher.CreateDecryptor(rijndaelCipher.Key, rijndaelCipher.IV);
            byte[] plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            return Encoding.UTF8.GetString(plainText);
        }
    }
}
