using System.Globalization;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace PowerEasy.WebFuture.DataMigrations.Foundation.Service
{
    /// <summary>
    /// 字符串扩展方法类。
    /// </summary>
    public static class StringExtensions
    {
        private static readonly Regex StyleLabel = new Regex(@"<style[^>]*?>[\s\S]*?<\/style>", RegexOptions.IgnoreCase);
        private static readonly Regex HtmlLabel = new Regex("<[^>]*>");
        private static readonly Regex NbspMark = new Regex("(&nbsp;|&#(160|(xA|xa)0?);)+");
        private static readonly Regex SqlKeywordRegex = new Regex(@"\b(SELECT|UPDATE|INSERT|DELETE|DECLARE|EXEC|DBCC|ALTER|DROP|CREATE|BACKUP|IF|ELSE|AND|OR|ADD|SET|OPEN|CLOSE|USE|BEGIN|RETUN|GO|EXISTS|KILL)\b", RegexOptions.IgnoreCase);
        private static readonly Regex ControlCharRegex = new Regex(@"[\x01-\x09]|[\x0B-\x0C]|[\x0E-\x1F]|[\x7F]", RegexOptions.Compiled);

        /// <summary>
        /// 替换特殊字符。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <returns>替换后的字符串。</returns>
        public static string ReplaceHtmlTag(this string originalString)
        {
            originalString = originalString.Replace("&lt;", "<");
            originalString = originalString.Replace("&gt;", ">");
            originalString = originalString.Replace("&amp;", "&");
            originalString = originalString.Replace("&apos;", "'");
            originalString = originalString.Replace("&quot;", "\"");
            return originalString;
        }

        /// <summary>
        /// 移除Html标识。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <param name="length">输出长度。</param>
        /// <returns>移除Html标识的字符串。</returns>
        public static string ReplaceHtmlTag(this string originalString, int length)
        {
            var strText = Regex.Replace(originalString, "<[^>]+>", string.Empty);
            strText = Regex.Replace(strText, "&[^;]+;", string.Empty);
            return SubString(strText, length, string.Empty);
        }

        /// <summary>
        /// 屏蔽指定长度的字符。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <param name="startPosition">开始位置。</param>
        /// <param name="length">遮蔽长度。</param>
        /// <returns>屏蔽之后的字符串。</returns>
        public static string Masking(this string originalString, int startPosition = 1, int length = 0)
        {
            string returnValue;
            if (startPosition < 1)
            {
                return originalString;
            }

            if (startPosition > originalString.Length - 1)
            {
                return originalString;
            }

            // 一直截取到最后。
            if (length < 1)
            {
                returnValue = originalString.Substring(0, startPosition) + string.Empty.PadRight(originalString.Length - startPosition, '*');
            }
            else
            {
                returnValue = originalString.Substring(0, startPosition) + string.Empty.PadRight(length, '*') + originalString.Substring(startPosition + length, originalString.Length - startPosition - length);
            }

            return returnValue;
        }

        /// <summary>
        /// 移除Html标识。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <param name="length">输出长度。</param>
        /// <param name="substring">替换字符串。</param>
        /// <returns>移除Html标识的字符串。</returns>
        public static string ReplaceHtmlTag(this string originalString, int length, string substring)
        {
            var strText = Regex.Replace(originalString, "<[^>]+>", string.Empty);
            strText = Regex.Replace(strText, "&[^;]+;", string.Empty);
            return SubString(strText, length, substring);
        }

        /// <summary>
        /// 删除文本中的Html标记。
        /// </summary>
        /// <param name="content">内容。</param>
        /// <returns>返回不包含Html标记的文本内容。</returns>
        public static string RemoveHtml(this string content)
        {
            if (string.IsNullOrEmpty(content))
            {
                return string.Empty;
            }

            // 如果内容含有<script></script>注释标签，要去掉。
            content = Regex.Replace(content, @"<script\b[^>]*>[\s\S]*<\/script>", string.Empty, RegexOptions.IgnoreCase);
            content = StyleLabel.Replace(content, string.Empty);
            content = NbspMark.Replace(content, " ");

            // 如果内容含有<!---->注释标签，要去掉。
            content = Regex.Replace(content, @"<!--[\s\S]*?-->", string.Empty, RegexOptions.Multiline);
            return HtmlLabel.Replace(content, string.Empty);
        }

        /// <summary>
        /// 文本中是否包含Html字符。
        /// </summary>
        /// <param name="content">文本。</param>
        /// <returns>返回是否包含Html字符。</returns>
        public static bool IsContainsHtml(this string content)
        {
            return HtmlLabel.IsMatch(content);
        }

        /// <summary>
        /// 在原来地址拼接后缀地址。
        /// </summary>
        /// <param name="path">字符串内容。</param>
        /// <param name="appendUrl">需要追加的路径。</param>
        /// <returns>返回后台子目录方式访问路径。</returns>
        public static string AppendUrl(this string path, string appendUrl)
        {
            if (path == null)
            {
                path = string.Empty;
            }

            if (appendUrl == null)
            {
                appendUrl = string.Empty;
            }

            if (path.EndsWith("/") && appendUrl.StartsWith("/"))
            {
                return path.TrimEnd('/') + appendUrl;
            }

            if (!path.EndsWith("/") && !appendUrl.StartsWith("/"))
            {
                return path + "/" + appendUrl;
            }

            return path + appendUrl;
        }

        /// <summary>
        /// 判断是否Ip地址。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <returns>是否是Ip地址。</returns>
        public static bool IsIpAddress(this string originalString)
        {
            if (originalString.IndexOf(":", StringComparison.Ordinal) > -1)
            {
                originalString = originalString.Substring(0, originalString.IndexOf(":", StringComparison.Ordinal));
            }

            return originalString.Equals("localhost", StringComparison.OrdinalIgnoreCase) || IPAddress.TryParse(originalString, out _);
        }

        /// <summary>
        /// 从地址栏参数中获取传递的值。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <param name="paramName">参数名。</param>
        /// <returns>是否是Ip地址。</returns>
        public static string GetParam(this string originalString, string paramName)
        {
            var paramValue = string.Empty;
            if (string.IsNullOrEmpty(originalString))
            {
                return paramValue;
            }

            var paramArr = originalString.Split('&');
            foreach (var item in paramArr)
            {
                var paramDic = item.Split('=');
                if (paramDic.Length > 1 && paramDic[0].ToLower() == paramName.ToLower())
                {
                    paramValue = WebUtility.UrlDecode(paramDic[1]);
                }
            }

            return paramValue;
        }

        /// <summary>
        /// 判断是否手机号码。
        /// </summary>
        /// <param name="originalString">原始字串。</param>
        /// <returns>是否是手机号码。</returns>
        public static bool IsPhone(this string originalString)
        {
            if (string.IsNullOrEmpty(originalString))
            {
                return false;
            }

            return Regex.IsMatch(originalString, @"^1(3[0-9]|4[57]|5[0-35-9]|6[6]|8[0-9]|9[012356789]|7[035678])\d{8}$");
        }

        /// <summary>
        /// 多行文本按行分组集合。
        /// </summary>
        /// <param name="text">文本内容。</param>
        /// <returns>行文本数组。</returns>
        public static string[] MultilineRows(this string text)
        {
            var rows = text?.TrimMultilineRows().Replace("\r\n", "\n").Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
            return rows;
        }

        /// <summary>
        /// 多行文本按行分组集合。
        /// </summary>
        /// <param name="text">文本内容。</param>
        /// <returns>行文本数组。</returns>
        public static string TrimMultilineRows(this string text)
        {
            return Regex.Replace(text.Trim(), @"[\f\t\v]", string.Empty);
        }

        /// <summary>
        /// 替换字符串起始位置(开头)中指定的字符串。
        /// </summary>
        /// <param name="s">源串。</param>
        /// <param name="searchStr">查找的串。</param>
        /// <param name="replaceStr">替换的字符串，默认为空字符串。</param>
        /// <param name="options">配置选项。</param>
        /// <returns>替换后的字符串。</returns>
        public static string TrimStarString(this string s, string searchStr, string replaceStr = "", RegexOptions options = RegexOptions.None)
        {
            return Regex.Replace(s, @"^(~(" + searchStr + ")+|(" + searchStr + ")+)", replaceStr, options);
        }

        /// <summary>
        /// 替换字符串末尾位置中指定的字符串。
        /// </summary>
        /// <param name="s">源串。</param>
        /// <param name="searchStr">查找的串。</param>
        /// <param name="replaceStr">替换的目标串。</param>
        /// <returns>替换后的字符串。</returns>
        public static string TrimEndString(this string s, string searchStr, string replaceStr)
        {
            var result = s;
            try
            {
                if (string.IsNullOrEmpty(result))
                {
                    return result;
                }

                if (s.Length < searchStr.Length)
                {
                    return result;
                }

                if (s.IndexOf(searchStr, s.Length - searchStr.Length, searchStr.Length, StringComparison.Ordinal) > -1)
                {
                    result = s.Substring(0, s.Length - searchStr.Length);
                }

                return result;
            }
            catch
            {
                return result;
            }
        }

        /// <summary>
        /// 替换特殊字符成全角字符。
        /// </summary>
        /// <param name="originalString">源字符串。</param>
        /// <returns>替换后的字符串。</returns>
        public static string ConvertToFullwidth(this string originalString)
        {
            if (!string.IsNullOrEmpty(originalString))
            {
                originalString = originalString.Replace("&lt;", "＜");
                originalString = originalString.Replace("&gt;", "＞");
                originalString = originalString.Replace("&amp;", "＆");
                originalString = originalString.Replace("&apos;", "＇");
                originalString = originalString.Replace("&quot;", "＂");
                originalString = originalString.Replace("<", "＜");
                originalString = originalString.Replace(">", "＞");
                originalString = originalString.Replace("&", "＆");
                originalString = originalString.Replace("'", "＇");
                originalString = originalString.Replace("\"", "＂");
            }

            return originalString;
        }

        /// <summary>
        /// 替换特殊字符成半角字符。
        /// </summary>
        /// <param name="originalString">源字符串。</param>
        /// <returns>替换后的字符串。</returns>
        public static string ConvertToDbcCase(this string originalString)
        {
            if (!string.IsNullOrEmpty(originalString))
            {
                originalString = originalString.Replace("&lt;", "<");
                originalString = originalString.Replace("&gt;", ">");
                originalString = originalString.Replace("&amp;", "&");
                originalString = originalString.Replace("&apos;", "'");
                originalString = originalString.Replace("&quot;", "\"");
                originalString = originalString.Replace("＜", "<");
                originalString = originalString.Replace("＞", ">");
                originalString = originalString.Replace("＆", "&");
                originalString = originalString.Replace("＇", "'");
                originalString = originalString.Replace("＂", "\"");
            }

            return originalString;
        }

        /// <summary>
        /// 检查Url是否是支付二维码地址。
        /// </summary>
        /// <param name="url">Url。</param>
        /// <returns>是返回true，否返回false。</returns>
        public static bool IsPayQRCode(this string url)
        {
            return url.ToLower().StartsWith("weixin://wxpay/bizpayurl") || url.ToLower().StartsWith("https://qr.alipay.com");
        }

        /// <summary>
        /// 判断手机号格式是否正确。
        /// </summary>
        /// <param name="originalString">字符串内容。</param>
        /// <returns>格式是否正确。</returns>
        public static bool CheckPhoneNumber(this string originalString)
        {
            if (originalString == null)
            {
                return false;
            }

            return Regex.IsMatch(originalString, "^1(3[0-9]|4[57]|5[0-35-9]|6[67]|8[0-9]|9[012356789]|7[01235678])\\d{8}$");
        }

        /// <summary>
        /// 判断邮箱格式是否正确。
        /// </summary>
        /// <param name="originalString">字符串内容。</param>
        /// <returns>格式是否正确。</returns>
        public static bool CheckEmail(this string originalString)
        {
            return Regex.IsMatch(originalString, "^((([a-z]|\\d|[!#\\$%&amp;'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+(\\.([a-z]|\\d|[!#\\$%&amp;'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(\\\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|\\d|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.)+(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])|(([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])([a-z]|\\d|-|\\.|_|~|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])*([a-z]|[\\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF])))\\.?$");
        }

        /// <summary>
        /// 时间戳转时间。
        /// </summary>
        /// <param name="timeStamp">时间戳。</param>
        /// <returns>返回时间。</returns>
        public static DateTime StampToDateTime(this string timeStamp)
        {
            TimeZoneInfo localTimeZone = TimeZoneInfo.Local;
            DateTime dateTimeStart = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Local);
            DateTime localDateTimeStart = TimeZoneInfo.ConvertTimeFromUtc(dateTimeStart, localTimeZone);
            long lTime = long.Parse(timeStamp + "0000000");
            TimeSpan toNow = new TimeSpan(lTime);
            return localDateTimeStart.Add(toNow);
        }

        /// <summary>
        /// 检查身份证是否符合规则。
        /// </summary>
        /// <param name="value">身份证。</param>
        /// <returns>是否是合法。</returns>
        public static bool CheckIdCard(this string value)
        {
            var isValid = false;
            if (value.Length == 15)
            {
                isValid = CheckIdCard15(value);
            }
            else if (value.Length == 18)
            {
                isValid = CheckIdCard18(value);
            }

            return isValid;
        }

        /// <summary>
        /// 过滤url的xss攻击。
        /// </summary>
        /// <param name="urlString">url。</param>
        /// <returns>返回过滤后的url。</returns>
        public static string FilterUrlXss(this string urlString)
        {
            if (string.IsNullOrEmpty(urlString))
            {
                return string.Empty;
            }

            const string Quot = "%22";
            const string Apos = "%27";
            const string Greater = "%3E";
            const string Less = "%3C";

            if (Regex.IsMatch(urlString, Quot) || Regex.IsMatch(urlString, Apos) || Regex.IsMatch(urlString, Greater) || Regex.IsMatch(urlString, Less))
            {
                urlString = Regex.Replace(urlString, Quot, string.Empty);
                urlString = Regex.Replace(urlString, Apos, string.Empty);
                urlString = Regex.Replace(urlString, Greater, string.Empty);
                urlString = Regex.Replace(urlString, Less, string.Empty);
                urlString = FilterUrlXss(urlString);
            }

            urlString = Regex.Replace(urlString, "\"", string.Empty);
            urlString = Regex.Replace(urlString, "\'", string.Empty);
            urlString = Regex.Replace(urlString, ">", string.Empty);
            urlString = Regex.Replace(urlString, "<", string.Empty);

            return urlString;
        }

        /// <summary>
        /// 获取当前字符串的字符数。（全角字符算2个字符数）。
        /// </summary>
        /// <param name="text">当前字符串。</param>
        /// <returns>当前字符串中字符的数量。</returns>
        public static int Length(this string text)
        {
            var length = 0;
            if (string.IsNullOrEmpty(text))
            {
                return length;
            }

            var ascii = new ASCIIEncoding();
            var bytes = ascii.GetBytes(text);
            for (int i = 0; i < bytes.Length; i++)
            {
                if (bytes[i] == 63)
                {
                    length += 2;
                }
                else
                {
                    length += 1;
                }
            }

            return length;
        }

        /// <summary>
        /// 分割换行符。
        /// </summary>
        /// <param name="text">文本。</param>
        /// <returns>结果。</returns>
        public static string[] SpiltLine(this string text)
        {
            if (string.IsNullOrWhiteSpace(text))
            {
                return new string[0];
            }

            var splitPath = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
            return splitPath;
        }

        /// <summary>
        /// 前台路径有条件的转为小写。content/_common/assets/ueditor目录下的不改为小写。
        /// </summary>
        /// <param name="path">原路径。</param>
        /// <returns>结果。</returns>
        public static string ToLowerPowerPath(this string path)
        {
            if (string.IsNullOrWhiteSpace(path))
            {
                return path;
            }

            // content/_common/assets/ueditor目录下不改为小写。
            var newPath = path.TrimStart(new char[] { '/', '\\', '~' }).Replace("\\", "/");
            if (newPath.StartsWith("content/_common/assets/ueditor/"))
            {
                return path;
            }

            return path.ToLower();
        }

        /// <summary>
        /// Encodes a URL string。
        /// </summary>
        /// <param name="value">字符串内容。</param>
        /// <returns>结果。</returns>
        public static string UrlEncode(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return value;
            }

            return HttpUtility.UrlEncode(value);
        }

        /// <summary>
        /// Converts a URL-encoded string into a decoded string, using the specified encoding object。
        /// </summary>
        /// <param name="value">字符串内容。</param>
        /// <returns>结果。</returns>
        public static string UrlDecode(this string value)
        {
            if (string.IsNullOrWhiteSpace(value))
            {
                return value;
            }

            return HttpUtility.UrlDecode(value);
        }

        /// <summary>
        /// 截取字符串(全角字符算一个)。
        /// </summary>
        /// <param name="value">原字符串。</param>
        /// <param name="maxLength">字符串保留的最大长度，超过此长度的部分会被丢弃。</param>
        /// <returns>如果字符串长度小于给定的长度，则返回原字符串。超过给定的长度，则从0开始截取指定长度。</returns>
        public static string SubstringText(this string value, int maxLength)
        {
            if (string.IsNullOrWhiteSpace(value) || maxLength <= 0)
            {
                return value;
            }

            if (value.Length > maxLength)
            {
                return value.Substring(0, maxLength);
            }

            return value;
        }

        /// <summary>
        /// 从右往左截取字符串(全角字符算一个)。
        /// </summary>
        /// <param name="value">原字符串。</param>
        /// <param name="maxLength">字符串保留的最大长度，超过此长度的部分会被丢弃。</param>
        /// <returns>如果字符串长度小于给定的长度，则返回原字符串。超过给定的长度，则从字符串末尾开始计算截取指定长度。</returns>
        public static string SubstringTextFromRight(this string value, int maxLength)
        {
            if (string.IsNullOrWhiteSpace(value) || maxLength <= 0)
            {
                return value;
            }

            if (value.Length > maxLength)
            {
                return value.Substring(value.Length - maxLength, maxLength);
            }

            return value;
        }

        /// <summary>
        /// 根据身份证号获取出生日期。
        /// </summary>
        /// <param name="idCard">身份证号。</param>
        /// <returns>操作结果</returns>
        public static DateTime GetBrithdayFromIdCard(this string idCard)
        {
            var birthday = DateTime.Now;
            if (string.IsNullOrEmpty(idCard))
            {
                return birthday;
            }

            if (idCard.Length == 15)
            {
                birthday = Convert.ToDateTime(idCard.Substring(6, 6).Insert(4, "-").Insert(2, "-"));
            }
            else if (idCard.Length == 18)
            {
                birthday = Convert.ToDateTime(idCard.Substring(6, 8).Insert(6, "-").Insert(4, "-"));
            }

            return birthday;
        }

        /// <summary>
        /// base64加密。
        /// </summary>
        /// <param name="original">原字符串。</param>
        /// <returns>base64字符串。</returns>
        public static string EncryptBase64ForJs(this string original)
        {
            var value1 = HttpUtility.UrlEncode(original);
            var bytes = Encoding.UTF8.GetBytes(value1);
            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// base64解密。
        /// </summary>
        /// <param name="base64String">base64字符串。</param>
        /// <returns>解密后的字符串。</returns>
        public static string DecryptBase64ForJs(this string base64String)
        {
            var bytes = Convert.FromBase64String(base64String);
            var tempValue = Encoding.UTF8.GetString(bytes);
            return HttpUtility.UrlDecode(tempValue);
        }

        /// <summary>
        /// 文本全角字符转半角字符
        /// </summary>
        /// <param name="input">输入的字符串</param>
        /// <param name="convertNumberOnly">是否只转换数字，默认：是</param>
        /// <returns>返回处理完毕的字符串。</returns>
        public static string Sbc2DbcText(this string input, bool convertNumberOnly = true)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                return input;
            }

            char[] c = input.ToCharArray();

            if (convertNumberOnly)
            {
                // 只转换数字
                for (int i = 0; i < c.Length; i++)
                {
                    if (c[i] >= '\uff10' && c[i] <= '\uff19')
                    {
                        // 全角与半角相差 65248
                        c[i] = (char)(c[i] - 65248);
                    }
                }
            }
            else
            {
                // 转换全部字符
                for (int i = 0; i < c.Length; i++)
                {
                    if (c[i] == 12288)
                    {
                        // 全角空格为12288，半角空格为32
                        c[i] = (char)32;
                        continue;
                    }

                    // 其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
                    if (c[i] > 65280 && c[i] < 65375)
                    {
                        c[i] = (char)(c[i] - 65248);
                    }
                }
            }

            return new string(c);
        }

        /// <summary>
        /// 隐藏字符串的中间字符。
        /// </summary>
        /// <param name="input">输入的字符串。</param>
        /// <param name="maxDisplayLength">左右最大显示的字符串。</param>
        /// <returns>返回隐藏后的字符串。</returns>
        /// <remarks>输入的字符串左右显示maxDisplayLength的字符后，中间显示*号。如果左右两边不够显示maxDisplayLength长度的字符，将减少显示长度。如果长度只有2时，左边显示一个字符，右边显示*。</remarks>
        public static string HideMiddleChar(this string input, int maxDisplayLength)
        {
            if (string.IsNullOrWhiteSpace(input))
            {
                return input;
            }

            string hiddenString;

            if (input.Length == 3)
            {
                hiddenString = input.Substring(0, 1) + "*" + input.Substring(input.Length - 1);
            }
            else if (input.Length == 2)
            {
                hiddenString = input.Substring(0, 1) + "*";
            }
            else if (input.Length == 1)
            {
                hiddenString = input;
            }
            else
            {
                // 不够最大显示数时,减少显示的长度。
                if (input.Length <= 2 * maxDisplayLength)
                {
                    maxDisplayLength = (input.Length / 2) - 1;
                }

                int middleLength = input.Length - (2 * maxDisplayLength);
                string middleHidden = string.Empty;
                for (int i = 0; i < middleLength; i++)
                {
                    // 中间的字符串全部用 * 代替
                    middleHidden += "*";
                }

                string leftDisplay = input.Substring(0, maxDisplayLength);

                int rightStartIndex = input.Length - maxDisplayLength;
                string rightDisplay = input.Substring(rightStartIndex);

                hiddenString = leftDisplay + middleHidden + rightDisplay;
            }

            return hiddenString;
        }

        /// <summary>
        /// 获取字符串的体积（以UTF-8计算）。
        /// </summary>
        /// <param name="text">字符串。</param>
        /// <returns>返回字符串体积（kb）。</returns>
        public static long GetStringVolume(this string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return 0;
            }

            byte[] bytes = Encoding.UTF8.GetBytes(text);
            long sizeInBytes = bytes.Length;
            long sizeInKilobytes = sizeInBytes / 1024;
            return sizeInKilobytes;
        }

        private static string GetFontName(int font)
        {
            switch (font)
            {
                case 1:
                    return "思源黑体 CN Regular";
                case 2:
                    return "思源宋体 CN";
                case 3:
                    return "黑体";
                case 4:
                    return "宋体";
                case 5:
                    return "楷体";
                default:
                    return "微软雅黑";
            }
        }

        /// <summary>
        /// 截取字符串。
        /// </summary>
        /// <param name="demand">要截取的字符串。</param>
        /// <param name="length">截取长度。</param>
        /// <param name="substitute">替换字符串。</param>
        /// <param name="keyword">搜索关键字。</param>
        /// <param name="clearSpacesDemand">是否清除要截取的字符串的空格。</param>
        /// <returns>截取后的字符串。</returns>
        private static string SubString(string demand, int length, string substitute, string keyword = null, bool clearSpacesDemand = false)
        {
            if (string.IsNullOrEmpty(demand))
            {
                return string.Empty;
            }

            if (clearSpacesDemand)
            {
                demand = demand.Replace(" ", string.Empty);
            }

            var start = 0;

            if (!string.IsNullOrEmpty(keyword) && length < demand.Length)
            {
                var index = demand.IndexOf(keyword, StringComparison.Ordinal);
                var check = (int)(index - Math.Floor(demand.Length / 2d));

                if (check > 0)
                {
                    start = (int)(index - Math.Floor(length / 2d));

                    if (start + length + 1 < demand.Length)
                    {
                        return substitute + demand.Substring(start, length) + substitute;
                    }

                    return substitute + demand.Substring(demand.Length - length);
                }

                return demand.Substring(0, length) + substitute;
            }

            if (string.IsNullOrEmpty(keyword) && Encoding.GetEncoding("GB2312").GetByteCount(demand) > length)
            {
                var ascii = new ASCIIEncoding();
                length = length - Encoding.GetEncoding("GB2312").GetByteCount(substitute);
                var factualLength = 0;
                var sb = new StringBuilder();
                var s = ascii.GetBytes(demand);
                for (var i = start; i < s.Length; i++)
                {
                    // 判断是否为汉字或全角符号
                    if (s[i] == 63)
                    {
                        factualLength += 2;
                    }
                    else
                    {
                        factualLength += 1;
                    }

                    if (factualLength > length)
                    {
                        break;
                    }

                    sb.Append(demand.Substring(i, 1));
                }

                sb.Append(substitute);
                return sb.ToString();
            }

            return demand;
        }

        private static string GetRootDomain(string url)
        {
            var splitHostName = url.Split('.');
            if (splitHostName.Length >= 2)
            {
                return splitHostName[splitHostName.Length - 2] + "." + splitHostName[splitHostName.Length - 1];
            }

            return null;
        }

        /// <summary>
        /// 18位身份证验证。
        /// </summary>
        /// <param name="id">身份证号。</param>
        /// <returns>验证结果。</returns>
        private static bool CheckIdCard18(string id)
        {
            long n;

            if (long.TryParse(id.Remove(17), out n) == false || n < Math.Pow(10, 16) || long.TryParse(id.Replace('x', '0').Replace('X', '0'), out n) == false)
            {
                return false;
            }

            const string Address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";

            if (Address.IndexOf(id.Remove(2), StringComparison.Ordinal) == -1)
            {
                return false;
            }

            var birth = id.Substring(6, 8).Insert(6, "-").Insert(4, "-");
            DateTime time;
            if (DateTime.TryParse(birth, out time) == false)
            {
                return false;
            }

            const string VerifyCode = "1,0,x,9,8,7,6,5,4,3,2";
            var arrVerifyCode = VerifyCode.Split(',');
            const string Wi = "7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2";
            var arrWi = Wi.Split(',');
            var arrAi = id.Remove(17).ToCharArray();
            var sum = 0;

            for (var i = 0; i < 17; i++)
            {
                sum += int.Parse(arrWi[i], CultureInfo.InvariantCulture) * int.Parse(arrAi[i].ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture);
            }

            int y;
            Math.DivRem(sum, 11, out y);

            if (arrVerifyCode[y].ToUpperInvariant() != id.Substring(17, 1).ToUpperInvariant())
            {
                return false;
            }

            return true;
        }

        /// <summary>
        /// 15位身份证验证。
        /// </summary>
        /// <param name="id">身份证号。</param>
        /// <returns>验证结果。</returns>
        private static bool CheckIdCard15(string id)
        {
            long n;

            if (long.TryParse(id, out n) == false || n < Math.Pow(10, 14))
            {
                return false;
            }

            const string Address = "11x22x35x44x53x12x23x36x45x54x13x31x37x46x61x14x32x41x50x62x15x33x42x51x63x21x34x43x52x64x65x71x81x82x91";

            if (Address.IndexOf(id.Remove(2), StringComparison.Ordinal) == -1)
            {
                return false;
            }

            var birth = id.Substring(6, 6).Insert(4, "-").Insert(2, "-");
            DateTime time;

            if (DateTime.TryParse(birth, out time) == false)
            {
                return false;
            }

            return true;
        }
    }
}