using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using System.Security.Cryptography;
using System.Web;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace CommonTools
{
    public static class Tools
    {

        /// <summary>
        /// 获取本地IP地址
        /// </summary>
        /// <returns></returns>
        public static string GetLocalIP()
        {
            string localIp = "";

            IPAddress[] addressList = Dns.GetHostAddresses(Dns.GetHostName());//会返回所有地址，包括IPv4和IPv6   
            foreach (IPAddress ip in addressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    localIp = ip.ToString();
                    break;
                }
            }

            return localIp;
        }
        /// <summary>
        /// 将主机名或 IP 地址解析IP地址
        /// </summary>
        /// <param name="domain"></param>
        /// <returns></returns>
        public static IPAddress GetIPByDomain(string hostNameOrAddress)
        {
            IPHostEntry host = Dns.GetHostEntry(hostNameOrAddress);
            return host.AddressList[0];
        }

        /// <summary>
        /// 获取本地IP地址列表
        /// </summary>
        /// <returns></returns>
        public static IList<string> GetLocalIPList()
        {
            IList<string> localIpList = new List<string>();

            IPAddress[] addressList = Dns.GetHostAddresses(Dns.GetHostName());//会返回所有地址，包括IPv4和IPv6   
            foreach (IPAddress ip in addressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    localIpList.Add(ip.ToString());
                }
            }

            return localIpList;
        }

        public static string GetApplicationPath()
        {
            return AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
        }
        /// <summary>
        /// 获取记录访问量文件路径
        /// </summary>
        /// <returns></returns>
        public static string GetCounterFilePath()
        {
            return GetApplicationPath() + @"License\counter.txt";
        }

        /// <summary>
        /// 生成CRC16校验
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        public static ushort CRC16(byte[] buffer, int len)
        {
            uint xda, xdapoly;
            byte xdabit;
            xda = 0xFFFF;
            xdapoly = 0xA001;	// (X**16 + X**15 + X**2 + 1)

            for (int i = 0; i < len; i++)
            {
                xda ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    xdabit = (byte)(xda & 0x01);
                    xda >>= 1;
                    if (xdabit == 1)
                    {
                        xda ^= xdapoly;
                    }
                }
            }
            return Convert.ToUInt16(xda & 0xffff);
        }

        /// <summary>
        /// 计算文件的MD5值
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        public static byte[] MD5(string file)
        {
            using (Stream stream = File.Open(file, FileMode.Open))
            {
                return MD5(stream);
            }
        }

        /// <summary>
        /// 计算流的MD5值
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static byte[] MD5(Stream stream)
        {
            using (MD5 md5 = new MD5CryptoServiceProvider())
            {
                return md5.ComputeHash(stream);
            }
        }
        /// <summary>
        /// 计算文件MD5
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string ComputeFileHash(Stream stream)
        {
            byte[] retVal = Tools.MD5(stream);
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++)
            {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        }

        /// <summary>
        /// 将MD5字符串转换成整型数组表示
        /// </summary>
        /// <param name="md5"></param>
        /// <returns></returns>
        public static uint[] MD5StringToUIntArray(string md5)
        {
            if (String.IsNullOrWhiteSpace(md5))
            {
                throw new ArgumentException("参数不能为空。", "md5");
            }

            try
            {
                uint[] md5Arr = new uint[4] { 0, 0, 0, 0 };

                md5Arr[0] = Convert.ToUInt32(md5.Substring(0, 8), 16);
                md5Arr[1] = Convert.ToUInt32(md5.Substring(8, 8), 16);
                md5Arr[2] = Convert.ToUInt32(md5.Substring(16, 8), 16);
                md5Arr[3] = Convert.ToUInt32(md5.Substring(24, 8), 16);

                return md5Arr;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("转换MD5出错。", ex);
            }
        }
        /// <summary>
        /// 用MD5加密字符串
        /// </summary>
        /// <param name="str">待加密的字符串</param>
        /// <returns></returns>
        public static string MD5Encrypt(string str)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] hashedDataBytes;
            hashedDataBytes = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(str));
            StringBuilder tmp = new StringBuilder();
            foreach (byte i in hashedDataBytes)
            {
                tmp.Append(i.ToString("x2"));
            }
            return tmp.ToString();
        }
        /// <summary>
        /// 获取指定长的的字符串对应的16进制字节码，如果长度不够，末位自动补0
        /// </summary>
        /// <param name="s"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static byte[] GetBytes(String str, int length)
        {
            byte[] s = System.Text.Encoding.GetEncoding("gb2312").GetBytes(str);
            int fixLength = length - s.Length;
            if (s.Length < length)
            {
                byte[] S_bytes = new byte[length];
                Array.Copy(s, 0, S_bytes, 0, s.Length);
                for (int x = length - fixLength; x < length; x++)
                {
                    S_bytes[x] = 0x00;
                }
                return S_bytes;
            }
            return s;
        }
        /// <summary>
        /// 获取一个随机数组
        /// </summary>
        /// <param name="num">数组个数</param>
        /// <param name="minValue"></param>
        /// <param name="maxValue"></param>
        /// <returns></returns>
        public static int[] GetRandomNum(int num, int minValue, int maxValue)
        {
            Random ra = new Random(unchecked((int)DateTime.Now.Ticks));
            int[] arrNum = new int[num];
            int tmp = 0;
            for (int i = 0; i <= num - 1; i++)
            {
                tmp = ra.Next(minValue, maxValue); //随机取数
                arrNum[i] = tmp;
            }
            return arrNum;
        }

        /// <summary> 
        /// 解决下载名称在IE下中文乱码 
        /// </summary> 
        /// <param name="s"></param> 
        /// <returns></returns> 
        public static String ToUtf8String(String s)
        {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < s.Length; i++)
            {
                char c = s[i];
                if (c >= 0 && c <= 255)
                {
                    sb.Append(c);
                }
                else
                {
                    byte[] b;
                    try
                    {
                        b = Encoding.UTF8.GetBytes(c.ToString());
                    }
                    catch (Exception)
                    {
                        b = new byte[0];
                    }
                    for (int j = 0; j < b.Length; j++)
                    {
                        int k = b[j];
                        if (k < 0) k += 256;

                        sb.Append("%" + Convert.ToString(k, 16).ToUpper());
                    }
                }
            }
            return sb.ToString();
        }
        /// <summary>
        /// 字节内容转换为字符串
        /// </summary>
        /// <param name="bytesData"></param>
        /// <returns></returns>
        public static string ByteToString(byte[] bytesData)
        {
            StringBuilder result = new StringBuilder();
            foreach (byte r in bytesData)
            {
                result.Append(r.ToString("X2") + " ");
            }
            return result.ToString();
        }
        /// <summary>
        /// 把int32类型的数据转存到2个字节的byte数组中
        /// </summary>
        /// <param name="m">int32类型的数据</param>
        /// <param name="arry">2个字节大小的byte数组</param>
        /// <returns></returns>
        public static byte[] Int32ToByte(Int32 data)
        {
            byte[] arry = new byte[2];
            arry[0] = (byte)((data & 0xFF00) >> 8);
            arry[1] = (byte)(data & 0xFF);
            return arry;
        }
        /// <summary>
        /// 把int32类型的数据转存到2个字节的byte数组中：小端
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] Int32ToByte2(Int32 data)
        {
            byte[] arry = new byte[2];
            arry[0] = (byte)(data & 0xFF);
            arry[1] = (byte)((data & 0xFF00) >> 8);
            //arry[2] = (byte)((data & 0xFF0000) >> 16);
            //arry[3] = (byte)((data >> 24) & 0xFF);

            return arry;
        }
        /// <summary>
        /// 2位byte转换为int类型
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static int ByteToInt(byte[] data)
        {
            return (data[1] & 0xFF) << 8 | data[0];
        }
        /// <summary>
        /// 4位byte转换为long类型
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static long Byte4ToLong(byte[] data)
        {
            return (data[3] << 24) & 0xFF | (data[2] & 0xFF00) << 16 | (data[1] & 0xFF) << 8 | data[0];
        }
        /// <summary>
        /// long类型转换为4位byte
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static byte[] LongToByte4(long data)
        {
            byte[] arry = new byte[4];
            arry[0] = (byte)(data & 0xFF);
            arry[1] = (byte)((data & 0xFF00) >> 8);
            arry[2] = (byte)((data & 0xFF0000) >> 16);
            arry[3] = (byte)((data >> 24) & 0xFF);

            return arry;
        }
        /// <summary> 
        /// 在指定时间过后执行指定的表达式 
        /// </summary> 
        /// <param name="interval">事件之间经过的时间（以毫秒为单位）</param> 
        /// <param name="action">要执行的表达式</param> 
        public static void SetTimeout(double interval, Action action)
        {
            System.Timers.Timer timer = new System.Timers.Timer(interval);
            timer.Elapsed += delegate (object sender, System.Timers.ElapsedEventArgs e)
            {
                timer.Enabled = false;
                action();
            };
            timer.Enabled = true;
        }

        /// <summary>   
        /// 得到字符串的长度，一个汉字算2个字符   
        /// </summary>   
        /// <param name="str">字符串</param>   
        /// <returns>返回字符串长度</returns>   
        public static int GetLength(string str)
        {
            if (str.Length == 0) return 0;

            ASCIIEncoding ascii = new ASCIIEncoding();
            int tempLen = 0;
            byte[] s = ascii.GetBytes(str);
            for (int i = 0; i < s.Length; i++)
            {
                if ((int)s[i] == 63)
                {
                    tempLen += 2;
                }
                else
                {
                    tempLen += 1;
                }
            }
            return tempLen;
        }
        /// <summary>  
        /// 获取枚举描述
        /// </summary>  
        /// <param name="en">枚举</param>  
        /// <returns>返回枚举的描述 </returns>  
        public static string GetDescription(Enum en)
        {
            Type type = en.GetType();//获取类型  
            MemberInfo[] memberInfos = type.GetMember(en.ToString());   //获取成员  
            if (memberInfos != null && memberInfos.Length > 0)
            {
                DescriptionAttribute[] attrs = memberInfos[0].GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];   //获取描述特性  
                if (attrs != null && attrs.Length > 0)
                {
                    return attrs[0].Description;    //返回当前描述
                }
            }
            return en.ToString();
        }
        /// <summary>
        /// stream to reader
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        public static string StreamToString(Stream stream)
        {
            stream.Position = 0;
            using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
            {
                return reader.ReadToEnd();
            }
        }
        /// <summary>
        /// HEX编码转换为——>ASCII编码
        /// </summary>
        /// <param name="Msg"></param>
        /// <returns></returns>
        public static string HexToASCII(string Msg)
        {
            byte[] buff = new byte[Msg.Length / 2];
            string Message = "";
            for (int i = 0; i < buff.Length; i++)
            {
                buff[i] = byte.Parse(Msg.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
            }
            System.Text.Encoding chs = System.Text.Encoding.ASCII;
            Message = chs.GetString(buff);
            return Message;
        }
        /// <summary>
        /// HEX编码转换为——>字符串
        /// </summary>
        /// <param name="Msg"></param>
        /// <returns></returns>
        public static string HexToStr(string Msg)
        {
            byte[] buff = new byte[Msg.Length / 2];
            string Message = "";
            for (int i = 0; i < buff.Length; i++)
            {
                buff[i] = byte.Parse(Msg.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
            }
            System.Text.Encoding chs = System.Text.Encoding.GetEncoding("gb2312");
            Message = chs.GetString(buff);
            return Message;
        }
        /// <summary>
        /// 字符串转化为——>HEX编码
        /// </summary>
        /// <param name="Msg"></param>
        /// <returns></returns>
        public static string StrToHex(string Msg)
        {
            byte[] bytes = System.Text.Encoding.Default.GetBytes(Msg);//转换为字节（十进制）
            string str = "";
            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);               //转换为十六进制
            }
            return str;
        }
        /// <summary>
        /// Hex文件解释
        /// </summary>
        /// <param name="filepath"></param>
        public static void HexFileRead(string filepath)//从指定文件目录读取HEX文件并解析，放入缓存数组buffer中
        {
            string szLine;
            int startAdr;
            int endAdr = 0;   //用于判断hex地址是否连续，不连续补充0xFF

            byte[] buffer = new byte[1024 * 1024 * 5]; // 打开文件hex to bin缓存
            int bufferAdr = 0;// 打开文件hex to bin缓存指针，用于计算bin的长度

            if (filepath == "")
            {
                return;
            }

            FileStream fsRead = new FileStream(filepath, FileMode.OpenOrCreate, FileAccess.Read);
            StreamReader HexReader = new StreamReader(fsRead); //读取数据流
            while (true)
            {
                szLine = HexReader.ReadLine(); //读取Hex中一行
                if (szLine == null) { break; } //读取完毕，退出
                if (szLine.Substring(0, 1) == ":") //判断首字符是”:”
                {
                    if (szLine.Substring(1, 8) == "00000001") { break; } //文件结束标识
                    if ((szLine.Substring(8, 1) == "0") || (szLine.Substring(8, 1) == "1"))//直接解析数据类型标识为 : 00 和 01 的格式
                    {
                        int lineLenth;
                        string hexString;

                        hexString = szLine.Substring(1, 2);
                        lineLenth = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber); // 获取一行的数据个数值

                        hexString = szLine.Substring(3, 4);
                        startAdr = Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber); // 获取地址值

                        for (int i = 0; i < startAdr - endAdr; i++) // 补空位置
                        {
                            hexString = "FF";
                            byte value = byte.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
                            buffer[bufferAdr] = value;
                            bufferAdr++;
                        }

                        for (int i = 0; i < lineLenth; i++) // hex转换为byte
                        {
                            hexString = szLine.Substring(i * 2 + 9, 2);
                            byte value = byte.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
                            buffer[bufferAdr] = value;
                            bufferAdr++;
                        }
                        endAdr = startAdr + lineLenth;
                    }
                }
            }
        }
        /// <summary>
        /// 将url参数转成json
        /// </summary>
        /// <param name="urlParams"></param>
        /// <returns></returns>
        public static string UrlParamsToJson(string urlParams)
        {
            var nameValueCollection = HttpUtility.ParseQueryString(urlParams);
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(nameValueCollection.AllKeys.ToDictionary(k => k, k => nameValueCollection[k]));
            return json;
        }
        //public static string GetUrl(string url)
        //{
        //    ComputeSignature();
        //    return "http://"+ url + "/?" +
        //        string.Join("&", _parameters.Select(x => x.Key + "=" + HttpUtility.UrlEncode(x.Value)));
        //}

        public static long GetCurrentTimeStamp(DateTime dt)
        {
            TimeSpan ts = dt - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Local);
            long current_timestamp = Convert.ToInt64(ts.TotalSeconds);
            return current_timestamp;
        }
        public static DateTime GetCurrentDateTime(long timestampMilliseconds)
        {
            DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
            DateTime utcTime = epoch.AddSeconds(timestampMilliseconds);
            return utcTime;
        }

        /// <summary>
        /// 格林尼治时间
        /// </summary>
        /// <returns></returns>
        public static long GetUnixTime()
        {
            DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            long unixTimestampMillisecondsManual = (long)(DateTime.UtcNow - unixEpoch).TotalSeconds;
            return unixTimestampMillisecondsManual;
        }
        public static long GetUnixTime_MS()
        {
            //DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            //double unixTimestampMillisecondsManual = (DateTime.UtcNow - unixEpoch).TotalMilliseconds;
            //return unixTimestampMillisecondsManual;

            return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();  // 返回 long
        }
        public static DateTime GetTimeFromUnixTime(long timestampSeconds)
        {
            // Unix 时间戳的起始时间（1970-01-01 00:00:00 UTC）
            DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);

            // 加上 Unix 时间戳的秒数
            return unixEpoch.AddSeconds(timestampSeconds);
        }


        public static byte CombineBitsToByte(bool bit0, bool bit1, bool bit2, bool bit3)
        {
            byte result = (byte)((bit0 ? 1 : 0) << 3); // 将bit0移到第4位（高位）
            result |= (byte)((bit1 ? 1 : 0) << 2); // 将bit1移到第3位
            result |= (byte)((bit2 ? 1 : 0) << 1); // 将bit2移到第2位
            result |= (byte)(bit3 ? 1 : 0); // 将bit3移到第1位（低位）
            return result;
        }

        /// <summary>
        /// 16进制字符串转换成 字节数组
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public static byte[] GetBytesFromString(string hexString)
        {
            hexString = DeleteSpaceChar(hexString);
            byte[] bytes = new byte[hexString.Length / 2]; // 计算字节数组的长度
            for (int i = 0; i < bytes.Length; i++)
            {
                bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16); // 每次取两个字符转换为字节
            }
            return bytes;
        }
        public static string DeleteSpaceChar(string originalString)
        {
            string result = Regex.Replace(originalString, @"\s", "");
            return result;
        }

        public static short HostNumberToHotelCode(string wer)
        {
            var v1 = wer.Substring(0, 3);
            var v2 = wer.Substring(3, 3);

            byte b12 = byte.Parse(v1);
            byte b13 = byte.Parse(v2);

            byte[] vva1 = new byte[] { b12, b13 };
            var usa = BitConverter.ToInt16(vva1, 0);
            return usa;
        }
    }
}
