using Apewer.Internals;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace Apewer
{

    /// <summary>文本实用工具。</summary>
    public class TextUtility
    {

        /// <summary>UTF-8 BOM。</summary>
        public static readonly byte[] Bom = Constant.Bom;

        /// <summary>空文本。</summary>
        public const string EmptyString = Constant.EmptyString;

        /// <summary>合并为字符串。</summary>
        public static string Merge(params object[] cells)
        {
            return Join(null, cells);
        }

        /// <summary>合并为字符串。</summary>
        public static string Merge(IEnumerable<object> cells)
        {
            return Join(null, (IEnumerable<object>)cells);
        }

        /// <summary>合并为字符串。</summary>
        public static string Join(string separator, params object[] cells)
        {
            return Join(separator, (IEnumerable<object>)cells);
        }

        /// <summary>合并为字符串。</summary>
        public static string Join(string separator, IEnumerable<object> cells)
        {
            if (cells == null) return Constant.EmptyString;
            var sb = new StringBuilder();
            var first = true;
            var hasSeparator = !string.IsNullOrEmpty(separator);
            foreach (var cell in cells)
            {
                // if (cell == null) continue;
                if (!first && hasSeparator) sb.Append(separator);
                first = false;

                if (cell == null) continue;
                var text = (cell is string) ? (string)cell : cell.ToString();
                if (string.IsNullOrEmpty(text)) continue;
                sb.Append(cell.ToString());
            }
            var result = sb.ToString();
            return result;
        }

        /// <summary>重复指定子字符串,直到达到指定长度。</summary>
        /// <param name="cell">子字符串。</param>
        /// <param name="length">目标字符串的长度。</param>
        public static string CopyChar(string cell, int length)
        {
            return TextGenerator.CopyChar(cell, length);
        }

        /// <summary>获取指定长的的空格。</summary>
        public static string Space(int length)
        {
            return TextGenerator.Space(length);
        }

        /// <summary>将文本以转换为字节数组。默认 Encoding 为 UTF-8。</summary>
        public static byte[] ToBinary(string text, Encoding encoding = null)
        {
            return TextConverter.ToBinary(text, encoding ?? Encoding.UTF8);
        }

        /// <summary>将字节数组转换为文本。默认 Encoding 为 UTF-8。</summary>
        public static string FromBinary(byte[] bytes, Encoding encoding = null)
        {
            if (bytes == null) return Constant.EmptyString;
            if (bytes.LongLength < 1L) return Constant.EmptyString;
            try
            {
                if (encoding == null) return FromBinary(bytes, Encoding.UTF8);
                return encoding.GetString(bytes);
            }
            catch { return Constant.EmptyString; }
        }

        /// <summary>将明文文本以 UTF-8 转换为 Base64 文本。</summary>
        public static string ToBase64(string plain)
        {
            return TextConverter.ToBase64(plain);
        }

        /// <summary>将 Base64 文本以 UTF-8 转换为明文文本。</summary>
        public static string FromBase64(string cipher)
        {
            return TextConverter.FromBase64(cipher);
        }

        /// <summary>byte -> plain</summary>
        public static string EncodeByte(byte @byte)
        {
            return TextConverter.EncodeByte(@byte);
        }

        /// <summary>binary -> hex plain</summary>
        public static string EncodeBinary(byte[] bytes)
        {
            return TextConverter.EncodeBinary(bytes);
        }

        /// <summary>hex text -> plain</summary>
        public static string EncodeText(string text, bool delimiter = false)
        {
            return TextConverter.EncodeText(text, delimiter);
        }

        /// <summary>hex plain -> binary</summary>
        public static byte[] DecodeBinary(string plain)
        {
            return TextConverter.DecodeBinary(plain);
        }

        /// <summary>hex plain -> text</summary>
        public static string DecodeText(string plain)
        {
            return TextConverter.DecodeText(plain);
        }

        /// <summary>将字节数组格式化为字符串。</summary>
        public static string FormatX2(params byte[] bytes)
        {
            return TextConverter.FormatX2(bytes);
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static Single GetFloat(char origin)
        {
            return TextConverter.GetSingle(origin.ToString());
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static Single GetFloat(string origin)
        {
            return TextConverter.GetSingle(origin);
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static Single GetSingle(char origin)
        {
            return TextConverter.GetSingle(origin.ToString());
        }

        /// <summary>获取单精度浮点对象。</summary>
        public static Single GetSingle(string origin)
        {
            return TextConverter.GetSingle(origin);
        }

        /// <summary>获取双精度浮点对象。</summary>
        public static Double GetDouble(char origin)
        {
            return TextConverter.GetDouble(origin.ToString());
        }

        /// <summary>获取双精度浮点对象。</summary>
        public static Double GetDouble(string origin)
        {
            return TextConverter.GetDouble(origin);
        }

        /// <summary>获取 Decimal 对象。</summary>
        public static decimal GetDecimal(char origin)
        {
            return TextConverter.GetDecimal(origin.ToString());
        }

        /// <summary>获取 Decimal 对象。</summary>
        public static decimal GetDecimal(string origin)
        {
            return TextConverter.GetDecimal(origin);
        }

        /// <summary>获取 Int16 对象。</summary>
        public static Int16 GetInt16(char origin)
        {
            return TextConverter.GetInt16(origin.ToString());
        }

        /// <summary>获取 Int16 对象。</summary>
        public static Int16 GetInt16(string origin)
        {
            return TextConverter.GetInt16(origin);
        }

        /// <summary>获取 Int32 对象。</summary>
        public static Int32 GetInt32(char origin)
        {
            return TextConverter.GetInt32(origin.ToString());
        }

        /// <summary>获取 Int32 对象。</summary>
        public static Int32 GetInt32(string origin)
        {
            return TextConverter.GetInt32(origin);
        }

        /// <summary>获取 Int64 对象。</summary>
        public static Int64 GetInt64(char origin)
        {
            return TextConverter.GetInt64(origin.ToString());
        }

        /// <summary>获取 Int64 对象。</summary>
        public static Int64 GetInt64(string origin)
        {
            return TextConverter.GetInt64(origin);
        }

        /// <summary>为字符串前添加字符“0”。</summary>
        /// <param name="origin">原字符串,内容应为整数、小数或十六进制数,若格式不符则返回原字符串。</param>
        /// <param name="length">新字符串的长度,若大于原数字长度,则不添加额外的“0”。</param>
        public static string PreZero(string origin, int length = 0)
        {
            return TextModifier.PreZero(origin, length);
        }

        /// <summary>删除字符串前额外的字符“0”。</summary>
        public static string RemoveZero(string argValue)
        {
            return TextModifier.RemoveZero(argValue);
        }

        /// <summary>替换父字符串中的子字符串。</summary>
        /// <param name="parent">父字符串。</param>
        /// <param name="new">新子字符串,保留大小写。</param>
        /// <param name="old">原子字符串。</param>
        /// <param name="ignoreCase">查找时是否忽略父字符串和原子字符串大小写。</param>
        /// <returns>替换后的父字符串。</returns>
        public static string Replace(string parent, string old, string @new, bool ignoreCase = false)
        {
            return TextModifier.Replace(parent, old, @new, ignoreCase);
        }

        /// <summary>修复文本后缀。默认用于修复 Windows 目录路径。</summary>
        /// <param name="origin">原文本。</param>
        /// <param name="include">True:追加指定后缀;False:去除指定后缀。</param>
        /// <param name="foot">后缀文本。</param>
        public static string AssureEnds(string origin, bool include = true, string foot = "\\")
        {
            return TextModifier.AssureEnds(origin, include, foot);
        }

        /// <summary>用单字符作为分隔符拆分文本。</summary>
        public static string[] Split(string text, char separator)
        {
            if (text == null) return new string[0];
            if (text.Length < 1) return new string[] { "" };
            if ((object)separator == null) return new string[] { text };

            return text.Split(separator);
        }

        /// <summary>用字符串作为分隔符拆分文本。</summary>
        public static string[] Split(string text, string separator)
        {
            if (text == null) return new string[0];
            if (text.Length < 1) return new string[] { "" };
            if (string.IsNullOrEmpty(separator)) return new string[] { text };
            if (separator.Length > text.Length) return new string[] { text };

            var list = new List<string>();
            var position = 0;
            var total = text.Length;
            var length = separator.Length;
            var cell = new StringBuilder();
            while (position < total)
            {
                var read = null as string;
                if (position + length < total) read = text.Substring(position, length);
                else read = text.Substring(position);

                if (read == separator)
                {
                    if (cell.Length > 0)
                    {
                        list.Add(cell.ToString());
                        // cell.Clear();
                        cell = new StringBuilder();
                    }
                    else
                    {
                        list.Add("");
                    }
                    position += length;
                }
                else
                {
                    cell.Append((char)text[position]);
                    position += 1;
                }

                if (position >= total)
                {
                    list.Add(cell.ToString());
                }
            }

            var array = list.ToArray();
            return array;
        }

        /// <summary>用多个分隔符拆分文本。</summary>
        public static string[] Split(string text, params char[] separators)
        {
            if (text == null) return new string[0];
            if (text.Length < 1) return new string[] { "" };
            if (separators == null || separators.Length < 1) return new string[] { text };
            if (separators.Length == 1) return Split(text, separators[0]);

            var list = new List<string>();
            var separatorsText = new string(separators);
            var sb = new StringBuilder();
            foreach (var c in text)
            {
                if (separatorsText.IndexOf(c) >= 0)
                {
                    list.Add(sb.ToString());
                    //sb.Clear();
                    sb = new StringBuilder();
                    continue;
                }
                sb.Append(c);
            }
            list.Add(sb.ToString());
#if !NET20
            sb.Clear();
#endif

            return list.ToArray();
        }

        /// <summary>移除字符串前后的空白。</summary>
        /// <param name="origin">原始字符串。</param>
        public static string Trim(string origin)
        {
            return TextModifier.Trim(origin);
        }

        /// <summary>移除字符串前后的空白。</summary>
        /// <param name="origin">原始字符串。</param>
        /// <param name="allCases">所有情况,全角空格将被去除。</param>
        public static string Trim(string origin, bool allCases)
        {
            return TextModifier.Trim(origin, allCases);
        }

        /// <summary>防注入处理,去除会引发代码注入的字符。可限定字符串长度。</summary>
        public static string AntiInject(string text, int length, params char[] blacklist)
        {
            return TextModifier.AntiInject(text, -1, blacklist);
        }

        /// <summary>防注入处理,去除会引发代码注入的字符。可限定字符串长度。</summary>
        public static string AntiInject(string text, int length, IEnumerable<char> blacklist)
        {
            return TextModifier.AntiInject(text, -1, blacklist);
        }

        /// <summary>防注入处理,去除会引发代码注入的字符。可限定字符串长度。</summary>
        public static string AntiInject(string text, int length = -1, string blacklist = Constant.InjectDefaultBlackList)
        {
            return TextModifier.AntiInject(text, -1, blacklist == null ? null : blacklist.ToCharArray());
        }

        /// <summary>剪取文本内容,若指定头部为空则从原文本首部起,若指定尾部为空则至原文本末尾。</summary>
        public static string Cut(string origin, string head = null, string foot = null)
        {
            return TextModifier.Cut(origin, head, foot);
        }

        /// <summary>比较两个字符串的相似度。返回值大于 0,小于等于 1。</summary>
        /// <param name="arg1"></param>
        /// <param name="arg2"></param>
        /// <returns></returns>
        public static double Similarity(string arg1, string arg2)
        {
            return Levenshtein.Compute(arg1, arg2).Rate;
        }

        /// <summary>判断对象为 Null、空字符串或空白字符串。</summary>
        public static bool IsEmpty(string text)
        {
            return TextVerifier.IsEmpty(text);
        }

        /// <summary>判断对象为含有内容的字符串。</summary>
        public static bool NotEmpty(string text)
        {
            return !TextVerifier.IsEmpty(text);
        }

        /// <summary>判断对象为 Null、空字符串或无实际内容的字符串。</summary>
        public static bool IsBlank(string text, bool allCases = false)
        {
            return TextVerifier.IsBlank(text, allCases);
        }

        /// <summary>判断对象为含有实际内容的字符串。</summary>
        public static bool NotBlank(string text, bool allCases = false)
        {
            return !TextVerifier.IsBlank(text, allCases);
        }

        /// <summary>生成新的 GUID(不带连字符、小写)。</summary>
        public static string NewGuid(bool hyphenation = false, bool lower = true)
        {
            var guid = Guid.NewGuid();
            if (!hyphenation && lower) return guid.ToString("n");

            var text = Guid.NewGuid().ToString();
            if (lower) text = text.ToLower();
            else text = text.ToUpper();
            if (!hyphenation) text = text.Replace("-", "");
            return text;
        }

        /// <summary>生成随机字符串,出现的字符由字符池指定,默认池包含数字和字母。</summary>
        /// <param name="pool">字符池,字符池中每个字符在随机字符串中出现的概率约等。</param>
        /// <param name="length">随机字符串的长度。</param>
        public static string Random(int length, string pool = "0123456789abcdefghijklmnopqrstuvwxyz")
        {
            return RandomHelper.RandomCustom(pool, length);
        }

        /// <summary>对字符串列表去重。指定 valid 参数时将去除 NULL、空字符串和空白字符串。</summary>
        public static List<string> Distinct(IEnumerable<string> origin, bool valid = false)
        {
            return TextModifier.Distinct(origin, valid);
        }

        /// <summary>约束字符串长度范围,超出的部分将被截取去除。</summary>
        public static string RestrictLength(string origin, int length)
        {
            return TextModifier.RestrictLength(origin, length);
        }

        /// <summary>约束字符串长度为 32,超出的部分将被截取去除。</summary>
        public static string Restrict32(string origin)
        {
            return TextModifier.RestrictLength(origin, 32);
        }

        /// <summary>约束字符串长度为 255,超出的部分将被截取去除。</summary>
        public static string Restrict255(string origin)
        {
            return TextModifier.RestrictLength(origin, 255);
        }

        /// <summary>约束字符串长度为 2000,超出的部分将被截取去除。</summary>
        public static string Restrict2000(string origin)
        {
            return TextModifier.RestrictLength(origin, 2000);
        }

        /// <summary>约束字符串中的字符,不允许的字符将被去除。</summary>
        public static string RestrictCharacters(string origin, params char[] allowable)
        {
            return TextModifier.RestrictCharacters(origin, new string(allowable));
        }

        /// <summary>约束字符串中的字符,不允许的字符将被去除。</summary>
        public static string RestrictCharacters(string origin, string allowable)
        {
            return TextModifier.RestrictCharacters(origin, allowable);
        }

        /// <summary>约束字符串中的字符,只保留字母。</summary>
        public static string RestrictLetters(string origin)
        {
            return TextModifier.RestrictCharacters(origin, Constant.LetterCollection);
        }

        /// <summary>约束字符串中的字符,只保留数字。</summary>
        public static string RestrictNumeric(string origin)
        {
            return TextModifier.RestrictCharacters(origin, Constant.NumberCollection);
        }

        /// <summary>约束字符串,只保留 GUID 可能出现的字符,根据连字符限定长度为 32 或 36。</summary>
        public static string RestrictGuid(string origin)
        {
            return TextModifier.RestrictGuid(origin);
        }

        /// <summary>追加字符串。</summary>
        public static void Append(StringBuilder builder, params object[] cells)
        {
            if (builder != null) builder.Append(Join(null, cells));
        }

        /// <summary>对 URL 编码。</summary>
        public static string EncodeUrl(string plain)
        {
            return UrlEncoding.Encode(plain);
        }

        /// <summary>对 URL 解码。</summary>
        public static string DecodeUrl(string escaped)
        {
            return UrlEncoding.Decode(escaped);
        }

        /// <summary>返回此字符串转换为小写形式的副本。</summary>
        public static string ToLower(string text)
        {
            if (text == null) return null;
            else if (text.Length < 1) return EmptyString;
            else return text.ToLower();
        }

        /// <summary>返回此字符串转换为大写形式的副本。</summary>
        public static string ToUpper(string text)
        {
            if (text == null) return null;
            else if (text.Length < 1) return EmptyString;
            else return text.ToUpper();
        }

        /// <summary>检查中国手机号码,包含 13x、14x、15x、16x、17x、18x 和 19x 号段。</summary>
        public static bool IsPhone(string phone)
        {
            if (string.IsNullOrEmpty(phone)) return false;
            var regex = new Regex(@"^(13|14|15|16|17|18|19)\d{9}$", RegexOptions.None);
            var match = regex.Match(phone);
            return match.Success;
        }

        /// <summary>合并用于启动进程的参数。</summary>
        public static string MergeProcessArgument(params object[] args)
        {
            // var special = " \"\n\r\b\t\f";

            var list = new List<string>();
            if (args != null)
            {
                foreach (var i in args)
                {
                    var arg = null as string;
                    if (i != null)
                    {
                        if (i is string) arg = i as string;
                        else arg = i.ToString();
                    }

                    if (string.IsNullOrEmpty(arg))
                    {
                        list.Add("\"\"");
                        continue;
                    }
                    if (arg.Contains(" ") || arg.Contains("\""))
                    {
                        list.Add(Merge("\"", arg.Replace("\"", "\\\""), "\""));
                        continue;
                    }
                    list.Add(arg);
                }
            }
            var result = Join(" ", list.ToArray());
            return result;
        }

        /// <summary>合并用于启动进程的参数。</summary>
        private static string MergeProcessArgument_2(params object[] args)
        {
            if (args == null) return "";
            if (args.Length < 1) return "";

            var sb = new StringBuilder();
            for (var i = 0; i < args.Length; i++)
            {
                if (i > 0) sb.Append(" ");

                var arg = null as string;
                if (args[i] != null)
                {
                    if (args[i] is string) arg = args[i] as string;
                    else arg = args[i].ToString();
                }

                if (arg.IsEmpty())
                {
                    sb.Append("\"\"");
                    continue;
                }

                // var special = " \"\n\r\b\t\f";
                var special = " \"";
                if (arg.IndexOfAny(special.ToCharArray()) < 0)
                {
                    sb.Append(arg);
                }
                else
                {
                    sb.Append("\"");
                    if (arg.NotEmpty())
                    {
                        foreach (var c in arg)
                        {
                            switch (c)
                            {
                                case '"':
                                    sb.Append("\\\"");
                                    break;
                                // case '\n':
                                //     sb.Append("\\n");
                                //     break;
                                // case '\r':
                                //     sb.Append("\\r");
                                //     break;
                                // case '\b':
                                //     sb.Append("\\b");
                                //     break;
                                // case '\t':
                                //     sb.Append("\\t");
                                //     break;
                                default:
                                    sb.Append(c);
                                    break;
                            }
                        }
                    }
                    sb.Append("\"");
                }
            }

            var result = sb.ToString();
            return result;
        }

    }

}