using System;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Security;

namespace ynhtm.Common
{
    /// <summary>
    /// 通用文本操作。
    /// </summary>
    public static class Text
    {
        public const string Null = (string)null;

        public const string VALIDATION_EMAIL = @"^[a-zA-Z0-9_]+([-+.'a-zA-Z0-9_]+)*@[a-zA-Z0-9_]+([-.a-zA-Z0-9_]+)*\.[a-zA-Z0-9_]+([-.a-zA-Z0-9_]+)*$";

        /// <summary>
        /// 重复复制字符。
        /// </summary>
        /// <param name="s">要复制的字符。</param>
        /// <param name="count">重复次数。</param>
        /// <returns>返回复制后的字符。</returns>
        public static string Replicate(this string s, int count)
        {
            if (s.IsNullOrEmpty()) return s;
            if (count < 1) throw new ArgumentOutOfRangeException("count");
            var result = "";
            for (var i = 0; i < count; i++)
                result += s;
            return result;
        }

        /// <summary>
        /// 指示指定的字符串是 null 还是 System.String.Empty 字符串。
        /// </summary>
        /// <param name="s">要测试的字符串。</param>
        /// <returns>如果 s 参数为 null 或空字符串 ("")，则为 true；否则为 false。</returns>
        public static bool IsNullOrEmpty(this string s)
        {
            return string.IsNullOrEmpty(s);
        }

        /// <summary>
        /// 指示指定的字符串是 null、空还是仅由空白字符组成。
        /// </summary>
        /// <param name="s">要测试的字符串。</param>
        /// <returns>如果 s 参数为 null 或 System.String.Empty，或者如果 s 仅由空白字符组成，则为 true。</returns>
        public static bool IsNullOrWhiteSpace(this string s)
        {
            return string.IsNullOrWhiteSpace(s);
        }

        /// <summary>
        /// 字符串是 null 或 System.String.Empty 时进行筛选。
        /// </summary>
        /// <param name="s">要测试的字符串。</param>
        /// <param name="defaultValue">如果 s 参数为 null 或空字符串 ("")，则为 true，则返回该参数。</param>
        /// <returns>根据条件按返回字符串。</returns>
        public static string IifNullOrEmpty(this string s, string defaultValue)
        {
            if (s.IsNullOrEmpty()) return defaultValue;
            return s;
        }

        /// <summary>
        /// 字符串是 null 或 System.String.Empty 时进行筛选。
        /// </summary>
        /// <param name="s">要测试的字符串。</param>
        /// <param name="defaultValue">如果 s 参数为 null 或 System.String.Empty，或者如果 s 仅由空白字符组成，则返回该参数。</param>
        /// <returns>根据条件按返回字符串。</returns>
        public static string IifNullOrWhiteSpace(this string s, string defaultValue)
        {
            if (s.IsNullOrWhiteSpace()) return defaultValue;
            return s;
        }

        /// <summary>
        /// 高亮标记关键字。
        /// </summary>
        /// <param name="s">要检索原始字符。</param>
        /// <param name="key">关键字。</param>
        /// <param name="style">高亮样式。</param>
        /// <returns>高亮标记的字符串。</returns>
        public static string Highlight(this string s, string key, string style = "background:yellow;color:red;")
        {
            if (s.IsNullOrWhiteSpace() || key.IsNullOrEmpty()) return s;
            return Regex.Replace(s, Regex.Escape(key), "<span style=\"" + style.Replace("$", "$$") + "\">$0</span>", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }

        /// <summary>
        /// 将字符串转换为 HTML 编码的字符串。
        /// </summary>
        /// <param name="s">要编码的字符串。</param>
        /// <returns>一个已编码的字符串。</returns>
        public static string HtmlEncode(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return HttpUtility.HtmlEncode(s);
        }

        /// <summary>
        /// 将已经为 HTTP 传输进行过 HTML 编码的字符串转换为已解码的字符串。
        /// </summary>
        /// <param name="s">要解码的字符串。</param>
        /// <returns>一个已解码的字符串。</returns>
        public static string HtmlDecode(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return HttpUtility.HtmlDecode(s);
        }

        /// <summary>
        /// 使用指定的编码对象对 URL 字符串进行编码。
        /// </summary>
        /// <param name="s">要编码的文本。</param>
        /// <param name="e">指定编码方案的 System.Text.Encoding 对象的名称，为空将以当前 HTTP 请求编码。</param>
        /// <returns>一个已编码的字符串。</returns>
        public static string UrlEncode(this string s, string e = null)
        {
            if (s.IsNullOrEmpty()) return s;
            if (e == null) return HttpContext.Current.Server.UrlEncode(s);
            return HttpUtility.UrlEncode(s, Encoding.GetEncoding(e));
        }

        /// <summary>
        /// 使用指定的编码对象将 URL 编码的字符串转换为已解码的字符串。
        /// </summary>
        /// <param name="s">要解码的字符串。</param>
        /// <param name="e">指定解码方案的 System.Text.Encoding 对象的名称，为空将以当前 HTTP 请求解码。</param>
        /// <returns>一个已解码的字符串。</returns>
        public static string UrlDecode(this string s, string e = null)
        {
            if (s.IsNullOrEmpty()) return s;
            if (e == null) return HttpContext.Current.Server.UrlDecode(s);
            return HttpUtility.UrlDecode(s, Encoding.GetEncoding(e));
        }

        /// <summary>
        /// 将字符串转换为 HTML 换行。
        /// </summary>
        /// <param name="s">要转换的字符串。</param>
        /// <returns>一个已转换的字符串。</returns>
        public static string HtmlWrap(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return s.Trim('\n').Replace("\n", "<br />");
        }

        /// <summary>
        /// 删除字符中的 HTML 标签。
        /// </summary>
        /// <param name="s">要删除的字符串。</param>
        /// <returns>一个已删除 HTML 标记的字符串。</returns>
        public static string HtmlDel(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return Regex.Replace(s, @"(<.*?(>|$)|\&[#a-zA-Z0-9_]+;)", "", RegexOptions.Compiled);
        }

        /// <summary>
        /// 将字符串最小限度地转换为 HTML 编码的字符串。
        /// </summary>
        /// <param name="s">要编码的字符串。</param>
        /// <returns>一个已编码的字符串。</returns>
        public static string AttributeEncode(this string s)
        {
            if (s.IsNullOrEmpty()) return s;
            return HttpUtility.HtmlAttributeEncode(s);
        }

        /// <summary>
        /// 剪切字符串。
        /// </summary>
        /// <param name="s">要剪切的字符串。</param>
        /// <param name="length">字符的最长长度。</param>
        /// <param name="modifier">超出长度后要追加的后缀字符串。</param>
        /// <returns>返回已经截取的字符串。</returns>
        public static string Substr(this string s, int length, string modifier = null)
        {
            if (s.IsNullOrEmpty()) return s;
            if (length <= 0) throw new ArgumentOutOfRangeException("length");
            if (s.Length > length) return s.Trim().Substring(0, length) + modifier;
            return s;
        }

        /// <summary>
        /// 生成一个适合于存储在配置文件中的 MD5 密码。
        /// </summary>
        /// <param name="s">要进行 MD5 加密的字符。</param>
        /// <returns>经过 MD5 加密的密码。</returns>
        public static string HashMD5(this string s)
        {
            if (s.IsNullOrWhiteSpace()) return s;
            return FormsAuthentication.HashPasswordForStoringInConfigFile(s, "MD5");
        }

        /// <summary>
        /// 判断字符串是否为 email 格式。
        /// </summary>
        /// <param name="s">要判断的字符串。</param>
        /// <returns>如果字符串是 email 格式，则为 true。</returns>
        public static bool IsEmail(string s)
        {
            if (s.IsNullOrWhiteSpace()) return false;
            return Regex.IsMatch(s, VALIDATION_EMAIL, RegexOptions.Compiled);
        }
    }
}
