using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace Quiz.Utility
{
	public static class Helper
	{
		const string _CHARS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
		const string _CHARNUMS = "0123456789";

		/// <summary>
		/// 获取当前北京时间。
		/// </summary>
		/// <returns></returns>
		public static DateTime BeiJingTimeNow()
		{
			return DateTime.UtcNow.AddHours(8d);
		}

		/// <summary>
		/// 其他时区时间转成北京时间
		/// </summary>
		/// <param name="timezone">时区</param>
		/// <param name="time">需要转换的时间</param>
		/// <returns></returns>
		public static DateTime BeiJingTimeGet(double timezone, DateTime time)
		{
			if (time == DateTime.MinValue || time == DateTime.MaxValue) return DateTime.MinValue;

			return time.AddHours(8 - timezone);
		}

		/// <summary>
		/// 北京时间转换成其他时间
		/// </summary>
		/// <param name="timezone">时区</param>
		/// <param name="time">需要转换的时间</param>
		/// <returns></returns>
		public static DateTime BeiJingTimeToLocal(double timezone, DateTime time)
		{
			if (time == DateTime.MinValue || time == DateTime.MaxValue) return DateTime.MinValue;

			return time.AddHours(timezone - 8);
		}

		/// <summary>
		/// 取字符串首字母(包括中文)
		/// </summary>
		/// <param name="c">字符串</param>
		/// <returns>首字母</returns>
		public static string GetFirstLetter(string c)
		{
			if (string.IsNullOrEmpty(c)) return "";
			var s = c.Substring(0, 1);
			if ((int)Convert.ToChar(s) > 0 && (int)Convert.ToChar(s) < 256) return "";
			byte[] array = System.Text.Encoding.Default.GetBytes(s);
			if (array == null || array.Length < 2) return "*";
			int i = (short)(array[0] - '\0') * 256 + ((short)(array[1] - '\0'));

			if (i < 0xB0A1) return "*";
			if (i < 0xB0C5) return "A";
			if (i < 0xB2C1) return "B";
			if (i < 0xB4EE) return "C";
			if (i < 0xB6EA) return "D";
			if (i < 0xB7A2) return "E";
			if (i < 0xB8C1) return "F";
			if (i < 0xB9FE) return "G";
			if (i < 0xBBF7) return "H";
			if (i < 0xBFA6) return "J";
			if (i < 0xC0AC) return "K";
			if (i < 0xC2E8) return "L";
			if (i < 0xC4C3) return "M";
			if (i < 0xC5B6) return "N";
			if (i < 0xC5BE) return "O";
			if (i < 0xC6DA) return "P";
			if (i < 0xC8BB) return "Q";
			if (i < 0xC8F6) return "R";
			if (i < 0xCBFA) return "S";
			if (i < 0xCDDA) return "T";
			if (i < 0xCEF4) return "W";
			if (i < 0xD1B9) return "X";
			if (i < 0xD4D1) return "Y";
			if (i < 0xD7FA) return "Z";
			return "*";
		}

		/// <summary>
		/// 检查给定位标志是否全满足条件。
		/// </summary>
		/// <param name="flag">给定的位标志。</param>
		/// <param name="consistent">检查的位满足真还是假。</param>
		/// <param name="sites">要检查的位集合。</param>
		/// <returns></returns>
		public static bool FlagAllCheck(int flag, bool consistent, params Enum[] sites)
		{
			if (sites == null) throw new ArgumentNullException("sites");
			bool c = true;
			for (int i = 0; i < sites.Length; i++)
			{
				int sv = (int)Enum.ToObject(sites[i].GetType(), sites[i]);
				c &= (((flag & sv) == sv) == consistent);
			}
			return c;
		}

		/// <summary>
		/// 检查给定位标志是否全满足真条件。
		/// </summary>
		/// <param name="flag">给定的位标志。</param>
		/// <param name="sites">要检查的位集合。</param>
		/// <returns></returns>
		public static bool FlagAllCheck(int flag, params Enum[] sites)
		{
			return FlagAllCheck(flag, true, sites);
		}

		/// <summary>
		/// 检查给定位标志是否任意满足条件。
		/// </summary>
		/// <param name="flag">给定的位标志。</param>
		/// <param name="consistent">检查的位满足真还是假。</param>
		/// <param name="sites">要检查的位集合。</param>
		/// <returns></returns>
		public static bool FlagAnyCheck(int flag, bool consistent, params Enum[] sites)
		{
			if (sites == null) throw new ArgumentNullException("sites");
			bool c = false;
			for (int i = 0; i < sites.Length; i++)
			{
				int sv = (int)Enum.ToObject(sites[i].GetType(), sites[i]);
				c |= (((flag & sv) == sv) == consistent);
				if (c) return c;
			}
			return c;
		}

		/// <summary>
		/// 检查给定位标志是否任意满足真条件。
		/// </summary>
		/// <param name="flag">给定的位标志。</param>
		/// <param name="sites">要检查的位集合。</param>
		/// <returns></returns>
		public static bool FlagAnyCheck(int flag, params Enum[] sites)
		{
			return FlagAnyCheck(flag, true, sites);
		}

		/// <summary>
		/// 获取当前时间刻度(6位)。
		/// </summary>
		/// <returns></returns>
		static string GetSecondTick()
		{
			DateTime time = DateTime.Now;
			time = time.ToUniversalTime();
			int ms = (time.DayOfYear - 1) * 86400;
			ms += time.Hour * 3660 + time.Minute * 60 + time.Second;
			return (Int32ToChar36(Math.Abs(time.Year - 2000)) + Int32ToChar36(ms).PadLeft(5, '0'));
		}

		/// <summary>
		/// 将给定的Int32类型转换成Char36字符串(如小于0,将返回空字符串)。
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static string Int32ToChar36(long value)
		{
			if (value <= 0) return "";
			string str = "";
			while (true)
			{
				if (value < 1) break;
				else if (value < _CHARS.Length)
				{
					int index = (int)value - 1;
					str = _CHARS[index] + str; break;
				}
				str = _CHARS[(int)((value - 1) % _CHARS.Length)] + str;
				value = (value - 1) / _CHARS.Length;
			}
			return str;
		}

		/// <summary>
		/// 将给定的Char36字符串转换成Int32类型(如字符串不能转换,将返回0)。
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static long Char36ToInt32(string value)
		{
			if (string.IsNullOrEmpty(value) || !System.Text.RegularExpressions.Regex.IsMatch(value, "^[0-9A-Z]+$", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) return 0;
			value = value.ToUpper();
			long r = 0;
			for (int i = value.Length - 1; i >= 0; i--) r += (_CHARS.IndexOf(value[i]) + 1) * (long)Math.Pow(36d, value.Length - i - 1);
			return r;
		}

		/// <summary>
		/// 递增一个给定的36进位编码数。
		/// </summary>
		/// <param name="value">要递增的编码数。</param>
		/// <returns></returns>
		public static string IncreaseChar36(string value)
		{
			return Int32ToChar36(Char36ToInt32(value) + 1);
		}

		/// <summary>
		/// 生成指定长度的随机字符串
		/// </summary>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string RandomString(int length)
		{
			if (length <= 0) throw new ArgumentOutOfRangeException("length");
			byte[] buffer1 = new byte[length];
			System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(buffer1);
			char[] rs = new char[length];
			for (int i = 0; i < length; i++) rs[i] = _CHARS[buffer1[i] % _CHARS.Length];
			return new string(rs);
		}

		/// <summary>
		/// 比较两个字符串是否相同(忽略null与Empty的不同,区分大小写)。
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		/// <returns></returns>
		public static bool StringCompare(string a, string b)
		{
			if (string.IsNullOrEmpty(a) && string.IsNullOrEmpty(b)) return true;
			else return a == b;
		}

		/// <summary>
		/// 生成指定长度数字随机字符串
		/// </summary>
		/// <param name="length"></param>
		/// <returns></returns>
		public static string RandomNumString(int length)
		{
			if (length <= 0) throw new ArgumentOutOfRangeException("length");
			byte[] buffer1 = new byte[length];
			System.Security.Cryptography.RandomNumberGenerator.Create().GetBytes(buffer1);
			char[] rs = new char[length];
			for (int i = 0; i < length; i++) rs[i] = _CHARNUMS[buffer1[i] % _CHARNUMS.Length];
			return new string(rs);
		}

		/// <summary>
		/// 生成根据时间刻度生成的20位标识符。
		/// </summary>
		/// <returns></returns>
		public static string Identifier20()
		{
			return GetSecondTick() + RandomString(14);
		}

        /// <summary>
        /// 获取订单号数值型
        /// </summary>
        /// <returns></returns>
        public static string NumIdentifier20()
        {
            DateTime time = DateTime.Now;
            return time.ToString("yyyyMMddHHmmss") + RandomNumString(4);
        }

		/// <summary>
		/// 生成根据时间刻度生成的10位标识符。
		/// </summary>
		/// <returns></returns>
		public static string Identifier10()
		{
			return GetSecondTick() + RandomString(4);
		}

		/// <summary>
		/// 生成根据时间刻度生成的12位标识符。
		/// </summary>
		/// <returns></returns>
		public static string Identifier12()
		{
			return GetSecondTick() + RandomString(6);
		}

		/// <summary>
		/// MD5加密。
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static string MD5(string value)
		{
			if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("value");
            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(value, "md5").ToUpper();
		}

		/// <summary>
		/// 提供DES算法对字符串进行加密。
		/// </summary>
		/// <param name="value">要加密的字符串。</param>
		/// <param name="key">加密使用的Key。</param>
		/// <returns></returns>
		public static string DESEnCode(string value, string key)
		{
			if (string.IsNullOrEmpty(value)) return null;
			if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");
			key = MD5(key).Substring(0, 8);
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			byte[] inputByteArray = Encoding.UTF8.GetBytes(value);
			des.Key = Encoding.UTF8.GetBytes(key);
			des.IV = Encoding.UTF8.GetBytes(key);
			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>
		/// 提供DES算法对字符串进行解密。
		/// </summary>
		/// <param name="value">要解密的字符串。</param>
		/// <param name="key">解密使用的Key。</param>
		/// <returns></returns>
		public static string DESDeCode(string value, string key)
		{
			if (string.IsNullOrEmpty(value)) return null;
			if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");
			key = MD5(key).Substring(0, 8);
			DESCryptoServiceProvider des = new DESCryptoServiceProvider();
			byte[] inputByteArray = new byte[value.Length / 2];
			for (int x = 0; x < (value.Length / 2); x++)
			{
				int i = System.Convert.ToInt32(value.Substring(x * 2, 2), 0x10);
				inputByteArray[x] = (byte)i;
			}
			des.Key = Encoding.UTF8.GetBytes(key);
			des.IV = Encoding.UTF8.GetBytes(key);
			MemoryStream ms = new MemoryStream();
			CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
			cs.Write(inputByteArray, 0, inputByteArray.Length);
			cs.FlushFinalBlock();
			StringBuilder ret = new StringBuilder();
			return Encoding.UTF8.GetString(ms.ToArray());
		}

        #region Url编码
        /// <summary>
        /// Url编码并对编码后的字符大写
        /// </summary>
        /// <param name="temp"></param>
        /// <returns></returns>
        public static string UrlEncode(string temp)
        {
            return UrlEncode(temp, Encoding.UTF8);
        }
        /// <summary>
        /// Url编码并对编码后的字符大写
        /// </summary>
        /// <param name="temp"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string UrlEncode(string temp, Encoding encoding)
        {
            if (string.IsNullOrEmpty(temp)) return string.Empty;
            StringBuilder stringBuilder = new StringBuilder();
            foreach (char item in temp)
            {
                string t = item.ToString();
                string k = HttpUtility.UrlEncode(t, encoding);
                stringBuilder.Append(t == k ? t : k.ToUpper());
            }
            return stringBuilder.ToString();
        }
        #endregion

        #region 生成日期随机码
        /// <summary>
        /// 生成日期随机码
        /// </summary>
        /// <returns></returns>
        public static string GetRamCode()
        {
            #region
            return DateTime.Now.ToString("yyyyMMddHHmmssffff");
            #endregion
        }
        #endregion

        #region 截取字符长度
        /// <summary>
        /// 截取字符长度
        /// </summary>
        /// <param name="inputString">字符</param>
        /// <param name="len">长度</param>
        /// <returns></returns>
        public static string CutString(string inputString, int len)
        {
            ASCIIEncoding ascii = new ASCIIEncoding();
            int tempLen = 0;
            string tempString = "";
            byte[] s = ascii.GetBytes(inputString);
            for (int i = 0; i < s.Length; i++)
            {
                if ((int)s[i] == 63)
                {
                    tempLen += 2;
                }
                else
                {
                    tempLen += 1;
                }

                try
                {
                    tempString += inputString.Substring(i, 1);
                }
                catch
                {
                    break;
                }

                if (tempLen > len)
                    break;
            }
            //如果截过则加上半个省略号 
            byte[] mybyte = System.Text.Encoding.Default.GetBytes(inputString);
            if (mybyte.Length > len)
                tempString += "…";
            return tempString;
        }
        #endregion

        #region 清除HTML标记
        public static string DropHTML(string Htmlstring)
        {
            //删除脚本  
            Htmlstring = Regex.Replace(Htmlstring, @"<script[^>]*?>.*?</script>", "", RegexOptions.IgnoreCase);
            //删除HTML  
            Htmlstring = Regex.Replace(Htmlstring, @"<(.[^>]*)>", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"([\r\n])[\s]+", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"-->", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"<!--.*", "", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(quot|#34);", "\"", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(amp|#38);", "&", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(lt|#60);", "<", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(gt|#62);", ">", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(nbsp|#160);", " ", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(iexcl|#161);", "\xa1", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(cent|#162);", "\xa2", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(pound|#163);", "\xa3", RegexOptions.IgnoreCase);
            Htmlstring = Regex.Replace(Htmlstring, @"&(copy|#169);", "\xa9", RegexOptions.IgnoreCase);

            Htmlstring = Regex.Replace(Htmlstring, @"&#(\d+);", "", RegexOptions.IgnoreCase);
            Htmlstring.Replace("<", "");
            Htmlstring.Replace(">", "");
            Htmlstring.Replace("\r\n", "");
            Htmlstring = HttpContext.Current.Server.HtmlEncode(Htmlstring).Trim();
            return Htmlstring;
        }
        #endregion

        #region 清除HTML标记且返回相应的长度
        public static string DropHTML(string Htmlstring, int strLen)
        {
            return CutString(DropHTML(Htmlstring), strLen);
        }
        #endregion

        #region 获得当前绝对路径
        /// <summary>
        /// 获得当前绝对路径
        /// </summary>
        /// <param name="strPath">指定的路径</param>
        /// <returns>绝对路径</returns>
        public static string GetMapPath(string strPath)
        {
            if (HttpContext.Current != null)
            {
                return HttpContext.Current.Server.MapPath(strPath);
            }
            else //非web程序引用
            {
                strPath = strPath.Replace("/", "\\");
                if (strPath.StartsWith("\\"))
                {
                    strPath = strPath.Substring(strPath.IndexOf('\\', 1)).TrimStart('\\');
                }
                return System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, strPath);
            }
        }
        #endregion

        #region SHA1加密
        public static String GetSha1(String str)
        {
            //建立SHA1对象
            SHA1 sha = new SHA1CryptoServiceProvider();
            //将mystr转换成byte[] 
            ASCIIEncoding enc = new ASCIIEncoding();
            byte[] dataToHash = enc.GetBytes(str);
            //Hash运算
            byte[] dataHashed = sha.ComputeHash(dataToHash);
            //将运算结果转换成string
            string hash = BitConverter.ToString(dataHashed).Replace("-", "");
            return hash;
        }
        #endregion

        #region 获取时间戳
        /// <summary>
        /// 获取时间戳
        /// </summary>
        /// <returns></returns>
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
        #endregion

        #region 写日志
        /// <summary>
        /// 写日志,可以指定文件名称
        /// </summary>
        /// <param name="str"></param>
        /// <param name="filename"></param>
        public static void SaveLog(string str, string filename)
        {
            try
            {
                if (filename == "")
                {
                    SaveLog(str);
                }
                else
                {
                    System.IO.File.AppendAllText(HttpContext.Current.Server.MapPath("~/Logs/") +
                        DateTime.Now.ToString("yyyyMMdd_") + filename + ".txt", string.Format(@"----------------
==={0}===
{1}
--------------", System.DateTime.Now.ToString(), str));
                }
            }
            catch { }
        }
        /// <summary>
        /// 写日志,用默认文件名
        /// </summary>
        /// <param name="str"></param>
        public static void SaveLog(string str)
        {
            System.IO.File.AppendAllText(HttpContext.Current.Server.MapPath("~/Logs/") + DateTime.Now.ToString("yyyyMMdd_") + "Log.txt", string.Format(@"----------------==={0}==={1}--------------", System.DateTime.Now.ToString(), str));
        }
        #endregion
	}
}