using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

namespace Long.Core.Extensions;

public static class StringExtensions
{
    public static bool IsNullOrEmpty(this string str)
    {
        return string.IsNullOrEmpty(str);
    }

    public static bool IsNullOrWhiteSpace(this string str)
    {
        return string.IsNullOrWhiteSpace(str);
    }

    /// <summary>
    /// 断言空值
    /// </summary>
    /// <param name="str"></param>
    /// <exception cref="ArgumentNullException"></exception>
    public static void AssertNullOrEmpty(this string str, string v)
    {
        if (string.IsNullOrEmpty(str))
        {
            throw new ArgumentNullException($"参数 {nameof(str)}：{v}");
        }
    }

    /// <summary>
    /// 断言空值或空白字符串
    /// </summary>
    /// <param name="str"></param>
    /// <exception cref="ArgumentNullException"></exception>
    public static void AssertNullOrWhiteSpace(this string str, string v)
    {
        if (string.IsNullOrWhiteSpace(str))
        {
            throw new ArgumentNullException($"参数 {nameof(str)}：{v}");
        }
    }

    public static T ConvertTo<T>(this string source) where T : struct
    {
        return (T)Convert.ChangeType(source, typeof(T));
    }

    public static string Left(this string str, int len)
    {
        if (str == null)
        {
            throw new ArgumentNullException("str");
        }

        if (str.Length < len)
        {
            throw new ArgumentException("len argument can not be bigger than given string's length!");
        }

        return str.Substring(0, len);
    }

    public static string NormalizeLineEndings(this string str)
    {
        return str.Replace("\r\n", "\n").Replace("\r", "\n").Replace("\n", Environment.NewLine);
    }

    public static int NthIndexOf(this string str, char c, int n)
    {
        if (str == null)
        {
            throw new ArgumentNullException("str");
        }

        int num = 0;
        for (int i = 0; i < str.Length; i++)
        {
            if (str[i] == c && ++num == n)
            {
                return i;
            }
        }

        return -1;
    }

    public static string RemovePostFix(this string str, params string[] postFixes)
    {
        if (str == null || str == string.Empty)
        {
            return string.Empty;
        }

        if (postFixes.IsNullOrEmpty())
        {
            return str;
        }

        foreach (string text in postFixes)
        {
            if (str.EndsWith(text))
            {
                return str.Left(str.Length - text.Length);
            }
        }

        return str;
    }

    public static string RemovePreFix(this string str, params string[] preFixes)
    {
        if (str == null || str == string.Empty)
        {
            return string.Empty;
        }

        if (preFixes.IsNullOrEmpty())
        {
            return str;
        }

        foreach (string text in preFixes)
        {
            if (str.StartsWith(text))
            {
                return str.Right(str.Length - text.Length);
            }
        }

        return str;
    }

    public static string Right(this string str, int len)
    {
        if (str == null)
        {
            throw new ArgumentNullException("str");
        }

        if (str.Length < len)
        {
            throw new ArgumentException("len argument can not be bigger than given string's length!");
        }

        return str.Substring(str.Length - len, len);
    }

    public static string[] Split(this string str, string separator)
    {
        return str.Split(new string[1] { separator }, StringSplitOptions.None);
    }

    public static string[] Split(this string str, string separator, StringSplitOptions options)
    {
        return str.Split(new string[1] { separator }, options);
    }

    public static string[] SplitToLines(this string str)
    {
        return Split(str, Environment.NewLine);
    }

    public static string[] SplitToLines(this string str, StringSplitOptions options)
    {
        return Split(str, Environment.NewLine, options);
    }

    public static T ToEnum<T>(this string value) where T : struct
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        return (T)Enum.Parse(typeof(T), value);
    }

    public static T ToEnum<T>(this string value, bool ignoreCase) where T : struct
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        return (T)Enum.Parse(typeof(T), value, ignoreCase);
    }

    public static string ToMd5(this string str)
    {
        using MD5 mD = MD5.Create();
        byte[] bytes = Encoding.UTF8.GetBytes(str);
        byte[] array = mD.ComputeHash(bytes);
        StringBuilder stringBuilder = new StringBuilder();
        byte[] array2 = array;
        foreach (byte b in array2)
        {
            stringBuilder.Append(b.ToString("X2"));
        }

        return stringBuilder.ToString();
    }

    #region 新增
    /// <summary>
    /// 是否是电子邮箱
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsEmail(this string str)
    {
        var reg = new Regex("^[a-zA-Z0-9.!#$%&'*+\\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$");
        return reg.IsMatch(str);
    }

    /// <summary>
    /// 是否是电话
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsPhone(this string str)
    {
        var reg = new Regex("^1(3|4|5|7|8|9)\\d{9}$");
        return reg.IsMatch(str);
    }

    /// <summary>
    /// 是否是密码
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsPassword(this string str)
    {
        var reg = new Regex("/^([a-z]|[A-Z]|[0-9]|[_-]){6,128}$");
        return reg.IsMatch(str);
    }

    /// <summary>
    /// 是否是 HTML
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsHTML(this string str)
    {
        return str.Length >= 3 && str.Substring(0, 1) == "<" && str.Substring(str.Length - 2, 1) == ">";
    }

    /// <summary>
    /// 是否是 XML
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsXML(this string str)
    {
        return str.IsHTML() && (str.IndexOf("<?xml") == 0 || str.IndexOf("<!DOCTYPE") == 0);
    }

    /// <summary>
    /// 是否是 JSON 字符串
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public static bool IsJSON(this string str)
    {
        var start = str.Substring(0, 1);
        var end = str.Substring(str.Length - 1, 1);
        return (start == "{" || start == "[") && (end == "}" || end == "]");
    }
    #endregion
}
