/*
 * 作者:吴隆健
 * 日期: 2019-04-07
 * 时间: 20:05
 * 
 */

using System;
using System.Text.RegularExpressions;
using System.Text;
using Newtonsoft.Json.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.IO;
using System.Data;

namespace MrWu.Basic
{

    /// <summary>
    /// 常用的一些方法_变量
    /// </summary>
    public static class BaseFun
    {

        private static readonly Random _random = new Random();

        /// <summary>
        /// 随机数
        /// </summary>
        public static Random random {
            get {
                return _random;
            }
        }

        /// <summary>
        /// 检查用户名_检查字符串只包含 字母数字 下划线
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="minlen">最小多长</param>
        /// <param name="maxlen">最大多长</param>
        /// <returns>true 表示通过  false 表示不通过</returns>
        public static bool CheckUserName(string username, int minlen, int maxlen)
        {
            //0-9    Ascii 48-57
            //a-z    Ascii 97-122
            //A-Z    Ascii 65-90
            //_      Ascii 95

            if (username == null)
                return false;
            //[]里面表示匹配a-z A-Z 0-9 _
            //如果前面在^表示匹配上述范围之外的
            //{n,m}表示匹配到n-m次
            //return Regex.IsMatch(username, @"^[a-zA-Z0-9]{3,6}");

            int len = username.Length;

            if (len < minlen || len > maxlen)
                return false;

            for (int i = 0; i < len; i++)
            {
                if (username[i] >= 97 && username[i] <= 122)
                    continue;
                if (username[i] >= 65 && username[i] <= 90)
                    continue;
                if (username[i] >= 48 && username[i] <= 57)
                    continue;
                if (username[i] == 95)
                    continue;
                return false;
            }
            return true;
        }
        
        public static bool CheckNickName(string nickname, int minlen, int maxlen)
        {
            if (nickname == null)
                return false;
            int len = nickname.Length;

            if (len < minlen || len > maxlen)
                return false;
            
            byte[] bts = Encoding.UTF8.GetBytes(nickname);
            for (int i = 0; i < len; i++)
            {
                if (bts[i] > 127 || (bts[i] >= 48 && bts[i] <= 57) || (bts[i] >= 65 && bts[i] <= 90) ||
                    (bts[i] >= 97 && bts[i] <= 122))
                    continue;
                return false;
            }
            return true;
        }

        static string SqlStr = @"and|or|exec|execute|insert|select|delete|update|alter|create|drop|count|\*|chr|char|asc|mid|substring|master|truncate|declare|xp_cmdshell|restore|backup|net +user|net +localgroup +administrators";

        /// <summary>
        /// Sql防注入
        /// </summary>
        /// <param name="inputString"></param>
        /// <returns>true 表示通过 fale 表示不通过</returns>
        public static bool ProcessSqlStr(string inputString)
        {
            if (string.IsNullOrEmpty(inputString))
                return true;

            //string SqlStr = 
            try
            {
                if ((inputString != null) && (inputString != String.Empty))
                {
                    string str_Regex = @"\b(" + SqlStr + @")\b";

                    Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
                    //string s = Regex.Match(inputString).Value;
                    if (true == Regex.IsMatch(inputString))
                        return false;

                }
            }
            catch
            {
                return false;
            }
            return true;
        }


        /// <summary>
        /// 字符串中是否包含SQL关键字
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool IsContainsSqlKey(string input)
        {
            if (string.IsNullOrEmpty(input))
            {
                return false;
            }

            if (input.IndexOf("'") >= 0) return false;

            string str_Regex = @"\b(" + SqlStr + @")\b";
            Regex Regex = new Regex(str_Regex, RegexOptions.IgnoreCase);
            return Regex.IsMatch(input);
        }

        /// <summary>
        /// 检查字符串是否都是数字
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static bool CheckStringIsNum(string input)
        {
            if (string.IsNullOrEmpty(input))
                return false;
            int len = input.Length;
            for (int i = 0; i < len; i++)
            {
                if (input[i] < 48 || input[i] > 57)
                    return false;
            }
            return true;
        }

        /// <summary>
        /// 检查字符串长度
        /// </summary>
        /// <param name="input">比较的字符串</param>
        /// <param name="minLength">最小长度</param>
        /// <param name="maxLength">最大长度</param>
        /// <param name="isCharLenth">true表示比较字符数量 false表示比较字节数量</param>
        /// <param name="encod">编码</param>
        /// <returns>是否符合规则 true 表示符合</returns>
        public static bool CheckStringLength(string input, int minLength, int maxLength, bool isCharLenth, Encoding encod)
        {
            if (input == null)
                return false;

            int len;
            if (isCharLenth)
            {
                len = input.Length;
            }
            else
            {
                byte[] bts = encod.GetBytes(input);
                len = bts.Length;
            }
            return len >= minLength && len <= maxLength;
        }

        /// <summary>
        /// 获取指定字节的字符串
        /// </summary>
        /// <param name="s">字符串</param>
        /// <param name="count">保留的长度</param>
        /// <param name="encod">编码</param>
        /// <returns></returns>
        public static string GetLengthString(string s, int count, Encoding encod)
        {

            if (string.IsNullOrEmpty(s))
                return s;

            char[] chars = s.ToCharArray();

            if (chars.Length < count)
                return s;

            for (int i = count - 1; i >= 0; i--)
            {
                int strCount = encod.GetByteCount(s.ToCharArray(), 0, i + 1);//加上字符的长度

                if (strCount <= count)
                    return s.Substring(0, i + 1);
            }
            return s;
        }

        /// <summary>
        /// 获取数组段组建的新数组
        /// </summary>
        /// <param name="ast">数组段</param>
        /// <returns>新数组</returns>
        public static T[] GetNewArray<T>(this ArraySegment<T> ast)
        {
            T[] tarray = new T[ast.Count];
            Array.Copy(ast.Array, ast.Offset, tarray, 0, ast.Count);
            return tarray;
        }

        /// <summary>
        /// 获取数组的一段
        /// </summary>
        /// <param name="array"></param>
        /// <param name="offset"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static T[] GetNewArray<T>(this T[] array, int offset, int count)
        {
            T[] tarrray = new T[count];
            Array.Copy(array, offset, tarrray, 0, count);
            return tarrray;
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="array"></param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="Asc"></param>
        public static void Sort(this int[] array, int left, int right, bool Asc = true)
        {
            for (int i = left; i < right; i++)
            {
                int index = i;
                for (int j = i + 1; j <= right; j++)
                {
                    if (Asc)
                    {
                        if (array[index] > array[j])
                        {
                            index = j;
                        }
                    }
                    else
                    {
                        if (array[index] < array[j])
                        {
                            index = j;
                        }
                    }
                }
                if (index != i)
                {
                    int temp = array[i];
                    array[i] = array[index];
                    array[index] = temp;
                }
            }
        }

        /// <summary>
        /// 快速排序
        /// </summary>
        /// <param name="array">数组</param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <param name="Asc"></param>
        /// <returns></returns>
        public static void QuickSort(this int[] array, int left, int right, bool Asc = true)
        {
            if (left >= right)
                return;
            int index = left + 1; //下一个要替换的值
            int i = index;
            while (i <= right)
            {
                if (Asc)
                {  //先把比第一个值大的放到第一个值前面
                    if (array[left] > array[i])
                    {
                        if (i != index)
                        {
                            int temp = array[index];
                            array[index] = array[i];
                            array[i] = temp;
                        }
                        index++;
                    }
                }
                else
                {
                    if (array[left] < array[i])
                    {
                        if (i != index)
                        {
                            int temp = array[index];
                            array[index] = array[i];
                            array[i] = temp;
                        }
                        index++;
                    }
                }
                i++;
            }
            index--;
            if (index != left)
            {
                int temp = array[index];
                array[index] = array[left];
                array[left] = temp;
            }

            array.QuickSort(left, index - 1, Asc);
            array.QuickSort(index + 1, right, Asc);
        }

        /// <summary>
        /// 二分法查找
        /// </summary>
        /// <param name="array">数组</param>
        /// <param name="value">值</param>
        /// <param name="left"></param>
        /// <param name="right"></param>
        /// <returns>查找到返回其位置,没找到返回其应该在的位置的相反数-1</returns>
        public static int FindIndex(this int[] array, int value, int left = 0, int right = -1)
        {
            if (array.Length == 0)
                return -1;

            if (right < 0)
                right = array.Length - 1;

            while (left <= right)
            {
                int midx = (left + right) / 2;
                if (array[midx] > value)
                    right = midx - 1;
                else if (array[midx] < value)
                    left = midx + 1;
                else
                    return midx;
            }

            return -left - 1;
        }

        /// <summary>
        /// 根据概率获取是否成功
        /// </summary>
        /// <param name="value">概率 0 - 1</param>
        /// <returns></returns>
        public static bool Probability(double value)
        {
            return random.NextDouble() < value;
        }

        /// <summary>
        /// 查找Jobject值
        /// </summary>
        /// <param name="jobject"></param>
        /// <param name="key"></param>
        /// <param name="isLow"></param>
        /// <returns></returns>
        public static JToken Find(this JObject jobject, string key, bool isLow = true)
        {
            if (key == null)
                return null;
            if (!isLow)
                return jobject[key];
            var kl = key.ToLower();
            foreach (var item in jobject.Properties())
            {
                if (item.Name.ToLower() == kl)
                    return item.Value;
            }
            return null;
        }

        /// <summary>
        /// 串连Jobject键值对
        /// </summary>
        /// <param name="jobject">要串联的jobject</param>
        /// <param name="separator">元素与元素之间的分隔符</param>
        /// <returns>链接好的字符串</returns>
        public static string Join(this JObject jobject, string separator = "&")
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in jobject)
            {
                sb.Append(item.Key);
                sb.Append("=");
                sb.Append(item.Value);
                sb.Append(separator);
            }
            if (sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }

        /// <summary>
        /// 串联IDictionary键值对
        /// </summary>
        /// <param name="dic">要串联的键值对</param>
        /// <param name="separator"> 元素与元素之间的分割符</param>
        /// <returns>链接好的字符串</returns>
        public static string Join(this IDictionary dic, string separator = "&")
        {
            StringBuilder sb = new StringBuilder();
            foreach (var item in dic.Keys)
            {
                sb.Append(item);
                sb.Append("=");
                sb.Append(dic[item]);
                sb.Append(separator);
            }
            if (sb.Length > 0)
                sb.Remove(sb.Length - 1, 1);
            return sb.ToString();
        }

        /// <summary>
        /// 获取字符的长度 汉字按2字符算 英文字母1字符算
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static int GetSeatLength(string key)
        {
            return Encoding.GetEncoding("GB2312").GetByteCount(key);
        }

        /// <summary>
        /// 键值对对齐
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="value">value</param>
        /// <param name="wight">小于0 左对齐 大于0右对齐</param>
        /// <returns></returns>
        public static string Align(string key, object value, int wight)
        {
            int bytelen = GetSeatLength(key);
            int strlen = key.Length;
            int count = bytelen - strlen;

            if (count < Math.Abs(wight))
            {
                //左对齐
                if (wight < 0)
                {
                    wight += count;
                }
                else
                {//右对齐 
                    wight -= count;
                }
            }


            string format = "{0," + wight + "}{1}";

            return string.Format(format, key, value);
        }


        

        /// <summary>
        /// 发送post包裹
        /// </summary>
        /// <param name="url">请求地址</param>
        /// <param name="body">数据</param>
        /// <param name="sty"></param>
        /// <param name="result">结果</param>
        /// <param name="timeout">超时时间 默认10秒钟</param>
        /// <param name="ua">UA</param>
        /// <returns></returns>
        public static HttpWebResponse HttpPost(string url, string body, ref string result, int sty = 1, int timeout = -1,string ua = null)
        {
            var tm0 = DateTime.Now;

            if (timeout == -1)
                timeout = 10000;

            HttpWebResponse response = null;

            Encoding encoding = Encoding.UTF8;
            //				url=HttpUtility.UrlEncode(url,encoding);
            try
            {
                //ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST";
                request.KeepAlive = false;
                request.Accept = "text/html, application/xhtml+xml, */*";
                if (!string.IsNullOrEmpty(ua))
                {
                    request.UserAgent = ua;
                }
                switch (sty)
                {
                    case 0:
                        request.ContentType = "application/x-www-form-urlencoded";
                        break;
                    case 1:
                        request.ContentType = "application/json";
                        break;
                    case 2:
                        request.ContentType = "application/octet-stream";
                        break;
                }
                request.Proxy = null;
                request.CookieContainer = new CookieContainer();//接收cookies
                if (timeout != -1)
                    request.Timeout = timeout;
                request.ReadWriteTimeout = 15000;
                byte[] buffer = encoding.GetBytes(body);
                request.ContentLength = buffer.Length;
                using (Stream stream = request.GetRequestStream())
                {
                    stream.Write(buffer, 0, buffer.Length);
                }
                
                response = (HttpWebResponse)request.GetResponse();

                using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                {
                    result = reader.ReadToEnd();
                }
                request.Abort();
            }
            catch (Exception e)
            {
                Console.WriteLine($"得到数据:{e.Message}");
                return null;
            }
            return response;
        }

        /// <summary>
        /// httpGet请求
        /// </summary>
        /// <param name="url">地址</param>
        /// <param name="result">结果</param>
        /// <param name="timeout">超时时间</param>
        /// <returns></returns>
        public static HttpWebResponse HttpGet(string url, ref string result, int timeout = -1)
        {

            if (timeout == -1)
                timeout = 10000;

            try
            {

                HttpWebResponse response = null;

                Encoding encoding = Encoding.UTF8;
                try
                {


                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                    //					request.KeepAlive=false;
                    request.Proxy = null;
                    request.Method = "GET";
                    request.Accept = "text/html, application/xhtml+xml, */*";
                    request.ContentType = "application/json";
                    //					switch(sty){
                    //							case 0:request.ContentType = "application/x-www-form-urlencoded";break;
                    //							case 1:request.ContentType = "application/json";break;
                    //							case 2:request.ContentType = "application/octet-stream";break;
                    //					}
                    //				request.CookieContainer = new CookieContainer();//接收cookies
                    if (timeout > 0)
                        request.Timeout = timeout;
                    request.ReadWriteTimeout = 15000;

                    response = (HttpWebResponse)request.GetResponse();

                    using (StreamReader reader = new StreamReader(response.GetResponseStream(), encoding))
                    {
                        result = reader.ReadToEnd();
                    }
                    request.Abort();
                    return response;
                }
                catch
                {
                    return null;
                }
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <summary>
        /// 数据表是否为 null 或空表
        /// </summary>
        /// <param name="table">表</param>
        /// <returns>返回结果</returns>
        public static bool DataTableIsNullOrEmpty(DataTable table)
        {
            return table == null || table.Rows == null || table.Rows.Count == 0;
        }

        /// <summary>
        /// 判断数据集是否是 null 或者空数据集
        /// </summary>
        /// <param name="dataset"></param>
        /// <returns></returns>
        public static bool DataSetIsNullOrEmpty(DataSet dataset)
        {
            return dataset == null || dataset.Tables == null || dataset.Tables.Count == 0;
        }

        /// <summary>
        /// 元素是否重复
        /// </summary>
        /// <param name="list"></param>
        /// <returns></returns>
        public static bool ItemRepeat<T>(IList<T> list)
        {
            int len = list.Count;
            IDictionary dic = new Dictionary<T, T>();
            for (int i = 0; i < len; i++)
            {
                if (dic.Contains(list[i]))
                    return true;
                dic.Add(list[i], list[i]);
            }
            return false;
        }

        /// <summary>
        /// 元素是否重复
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="thesame">比较器</param>
        /// <returns></returns>
        public static bool ItemRepeat<T>(IList<T> list, Func<T, T, bool> thesame)
        {
            int len = list.Count;
            for (int i = 0; i < len; i++)
            {
                for (int j = i + 1; j < len; j++)
                {
                    if(thesame(list[i],list[j]))
                        return true;
                }
            }
            return false;
        }

    }
}
