using Microsoft.VisualBasic.CompilerServices;
using System;
using System.Globalization;
using System.Text;

namespace Siger.ApiQMS.Utility
{
    public static class StringsHelper
    {
        /// <summary>返回与指定字符代码相关联的字符。</summary>
        /// <param name="CharCode">必需。 <see langword="Integer" /> 表达式，表示字符的 code point 或字符代码。</param>
        /// <returns>与指定字符代码相关联的字符。</returns>
        /// <exception cref="T:System.ArgumentException">
        /// <see langword="Chr" /> 的 <paramref name="CharCode" /> &lt; 0 或 &gt; 255。</exception>
        public static char Chr(int CharCode)
        {
            if (CharCode < (int)short.MinValue || CharCode > (int)ushort.MaxValue)
                throw new Exception("Chr Error");
            if (CharCode >= 0 && CharCode <= (int)sbyte.MaxValue)
                return Convert.ToChar(CharCode);
            try
            {
                Encoding encoding = Encoding.Default;//Encoding.GetEncoding(UtilsHelper.GetLocaleCodePage());
                if (encoding.IsSingleByte && (CharCode < 0 || CharCode > (int)byte.MaxValue))
                    throw new Exception("Chr Error");
                char[] chars = new char[2];
                byte[] bytes = new byte[2];
                Decoder decoder = encoding.GetDecoder();
                if (CharCode >= 0 && CharCode <= (int)byte.MaxValue)
                {
                    bytes[0] = checked((byte)(CharCode & (int)byte.MaxValue));
                    decoder.GetChars(bytes, 0, 1, chars, 0);
                }
                else
                {
                    bytes[0] = checked((byte)((CharCode & 65280) >> 8));
                    bytes[1] = checked((byte)(CharCode & (int)byte.MaxValue));
                    decoder.GetChars(bytes, 0, 2, chars, 0);
                }
                return chars[0];
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>返回数组的指示维度的最大可用下标。</summary>
        /// <param name="Array">必需。 任何数据类型的数组。 要在其中查找维度的最大可能下标的数组。</param>
        /// <param name="Rank">可选。 <see langword="Integer" />。 将返回其最大可用下标的维度。 对第一维使用 1，对第二维使用 2，依此类推。 如果省略 <paramref name="Rank" />，则假定为 1。</param>
        /// <returns>
        /// <see langword="Integer" />。 指定维度的下标可以包含的最大值。 如果 <paramref name="Array" /> 只有一个元素，则 <see langword="UBound" /> 返回 0。 如果 <paramref name="Array" /> 没有元素，例如它是一个零长度字符串，则 <see langword="UBound" /> 返回 -1。</returns>
        /// <exception cref="T:System.ArgumentNullException">
        /// <paramref name="Array" /> 为 <see langword="Nothing" />。</exception>
        /// <exception cref="T:System.RankException">
        /// <paramref name="Rank" /> 小于 1，或 <paramref name="Rank" /> 大于 <paramref name="Array" /> 的级别。</exception>
        public static int UBound(Array Array, int Rank = 1)
        {
            if (Array == null)
                //throw ExceptionUtils.VbMakeException((Exception)new ArgumentNullException(Utils.GetResourceString("Argument_InvalidNullValue1", new string[1]
                //{
                //    nameof (Array)
                //})), 9);
                throw new Exception("UBound Error");
            if (Rank < 1 || Rank > Array.Rank)
                //throw new RankException(Utils.GetResourceString("Argument_InvalidRank1", new string[1]
                //{
                //    nameof (Rank)
                //}));
                throw new Exception("UBound Error");
            return Array.GetUpperBound(checked(Rank - 1));
        }

        /// <summary>返回字符串，该字符串包含从字符串中的指定位置开始的指定数量的字符。</summary>
        /// <param name="str">必需。 <see langword="String" /> 表达式，从该表达式返回字符。</param>
        /// <param name="Start">必需。 <see langword="Integer" /> 表达式。 要返回字符的开始位置。 如果 <paramref name="Start" /> 大于 <paramref name="str" /> 中的字符个数，则 <see langword="Mid" /> 函数返回零长度字符串 ("")。 <paramref name="Start" /> 从 1 开始。</param>
        /// <param name="Length">可选。 <see langword="Integer" /> 表达式。 要返回的字符数。 如果 <paramref name="Length" /> 省略或超过文本的字符（包括 <paramref name="Start" /> 处的字符）数，则返回从字符串开始位置到结尾的所有字符。</param>
        /// <returns>由从字符串中指定位置开始的指定数量的字符组成的字符串。</returns>
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="Start" /> &lt;= 0 或 <paramref name="Length" /> &lt; 0。</exception>
        public static string Mid(string str, int Start, int Length)
        {
            if (Start <= 0)
                //throw new ArgumentException(Utils.GetResourceString("Argument_GTZero1", new string[1]
                //{
                //    nameof (Start)
                //}));
                throw new Exception("Mid Error");
            if (Length < 0)
                //throw new ArgumentException(Utils.GetResourceString("Argument_GEZero1", new string[1]
                //{
                //    nameof (Length)
                //}));
                throw new Exception("Mid Error");
            string str1;
            if (Length == 0 || str == null)
            {
                str1 = "";
            }
            else
            {
                int length = str.Length;
                str1 = Start <= length ? (checked(Start + Length) <= length ? str.Substring(checked(Start - 1), Length) : str.Substring(checked(Start - 1))) : "";
            }
            return str1;
        }

        /// <summary>返回一个字符串，其中的指定子字符串已由另一个子字符串替换了指定的次数。</summary>
        /// <param name="Expression">必需。 字符串表达式，包含要替换的子字符串。</param>
        /// <param name="Find">必需。 搜索的子字符串。</param>
        /// <param name="Replacement">必需。 替换用的子字符串。</param>
        /// <param name="Start">可选。 <paramref name="Expression" /> 内部要替换的子字符串的开始的位置。 <see langword="Replace" /> 的返回值是字符串，在 <paramref name="Start" /> 开始，具有相应的子情况。 如果省略，则假定为 1。</param>
        /// <param name="Count">可选。 执行子字符串替换的数目。 如果省略，则默认值是 -1，表示“进行所有可能的替换”。</param>
        /// <param name="Compare">可选。 数值，指示对子字符串求值时使用的比较类型。 具体的值请参见"设置"。</param>
        /// <returns>
        ///        <see langword="Replace" /> 返回下列值。
        ///  如果
        ///  Replace 返回
        /// <paramref name="Find" /> 的长度为零或 <see langword="Nothing" /><paramref name="Expression" /> 的副本的长度为零
        ///  <paramref name="Expression" /> 的副本，不带 <paramref name="Find" /> 匹配项<paramref name="Expression" /> 的长度为零或 <see langword="Nothing" />，或者 <paramref name="Start" /> 大于 <paramref name="Expression" /> 的长度<see langword="Nothing" /><paramref name="Count" /> 是 0
        ///  <paramref name="Expression" /> 的副本</returns>
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="Count" /> &lt; -1 或 <paramref name="Start" /> &lt;= 0。</exception>
        public static string Replace(string Expression, string Find, string Replacement, int Start = 1, int Count = -1, [OptionCompare] CompareMethod Compare = CompareMethod.Binary)
        {
            try
            {
                if (Count < -1)
                    //throw new ArgumentException(Utils.GetResourceString("Argument_GEMinusOne1", new string[1]
                    //{
                    //    nameof (Count)
                    //}));
                    throw new Exception("Replace Error");
                if (Start <= 0)
                    //throw new ArgumentException(Utils.GetResourceString("Argument_GTZero1", new string[1]
                    //{
                    //    nameof (Start)
                    //}));
                    throw new Exception("Replace Error");
                if (Expression == null || Start > Expression.Length)
                    return (string)null;
                if (Start != 1)
                    Expression = Expression.Substring(checked(Start - 1));
                if (Find != null && Find.Length != 0)
                {
                    switch (Count)
                    {
                        case -1:
                            Count = Expression.Length;
                            break;
                        case 0:
                            goto label_10;
                    }
                    return ReplaceInternal(Expression, Find, Replacement, Count, Compare);
                }
                label_10:
                return Expression;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        internal static readonly CompareInfo m_InvariantCompareInfo = CultureInfo.InvariantCulture.CompareInfo;

        private static string ReplaceInternal(string Expression, string Find, string Replacement, int Count, CompareMethod Compare)
        {
            int length1 = Expression.Length;
            int length2 = Find.Length;
            StringBuilder stringBuilder = new StringBuilder(length1);
            CompareInfo compareInfo;
            CompareOptions options;
            if (Compare == CompareMethod.Text)
            {
                compareInfo = UtilsHelper.GetCultureInfo().CompareInfo;
                options = CompareOptions.IgnoreCase | CompareOptions.IgnoreKanaType | CompareOptions.IgnoreWidth;
            }
            else
            {
                compareInfo = m_InvariantCompareInfo;
                options = CompareOptions.Ordinal;
            }
            int num1;
            int num2 = 0;//可能有问题
            for (var startIndex = 0; startIndex < length1; startIndex = checked(num1 + length2))
            {
                if (num2 == Count)
                {
                    stringBuilder.Append(Expression.Substring(startIndex));
                    break;
                }
                num1 = compareInfo.IndexOf(Expression, Find, startIndex, options);
                if (num1 < 0)
                {
                    stringBuilder.Append(Expression.Substring(startIndex));
                    break;
                }
                stringBuilder.Append(Expression.Substring(startIndex, checked(num1 - startIndex)));
                stringBuilder.Append(Replacement);
                checked { ++num2; }
            }
            return stringBuilder.ToString();
        }

        /// <summary>返回一个字符串，它包含一个没有前导空格 (<see langword="LTrim" />)、没有尾随空格 (<see langword="RTrim" />) 或既没有前导空格也没有尾随空格 (<see langword="Trim" />) 的指定字符串的副本。</summary>
        /// <param name="str">必需。 任何有效的 <see langword="String" /> 表达式。</param>
        /// <returns>一个字符串，它包含一个没有前导空格 (<see langword="LTrim" />)、没有尾随空格 (<see langword="RTrim" />) 或既没有前导空格也没有尾随空格 (<see langword="Trim" />) 的指定字符串的副本。</returns>
        public static string Trim(string str)
        {
            try
            {
                if (str == null || str.Length == 0)
                    return "";
                switch (str[0])
                {
                    case ' ':
                    case '　':
                        return str.Trim(UtilsHelper.m_achIntlSpace);
                    default:
                        switch (str[checked(str.Length - 1)])
                        {
                            case ' ':
                            case '　':
                                return str.Trim(UtilsHelper.m_achIntlSpace);
                            default:
                                return str;
                        }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>返回表示与某个字符相对应的字符代码的整数值。</summary>
        /// <param name="String">必需。 任何有效的 <see langword="Char" /> 或 <see langword="String" /> 表达式。 如果 <paramref name="String" /> 是一个 <see langword="String" /> 表达式，则只将字符串的第一个字符用于输入。 如果 <paramref name="String" /> 是 <see langword="Nothing" /> 或不包含任何字符，将会出现 <see cref="T:System.ArgumentException" /> 错误。</param>
        /// <returns>与某个字符相对应的字符代码。</returns>
        public static int Asc(char String)
        {
            int int32 = Convert.ToInt32(String);
            if (int32 < 128)
                return int32;
            try
            {
                Encoding fileIoEncoding = UtilsHelper.GetFileIOEncoding();
                char[] chars = new char[1] { String };
                if (fileIoEncoding.IsSingleByte)
                {
                    byte[] bytes = new byte[1];
                    fileIoEncoding.GetBytes(chars, 0, 1, bytes, 0);
                    return (int)bytes[0];
                }
                byte[] bytes1 = new byte[2];
                if (fileIoEncoding.GetBytes(chars, 0, 1, bytes1, 0) == 1)
                    return (int)bytes1[0];
                if (BitConverter.IsLittleEndian)
                {
                    byte num = bytes1[0];
                    bytes1[0] = bytes1[1];
                    bytes1[1] = num;
                }
                return (int)BitConverter.ToInt16(bytes1, 0);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>返回表示与某个字符相对应的字符代码的整数值。</summary>
        /// <param name="String">必需。 任何有效的 <see langword="Char" /> 或 <see langword="String" /> 表达式。 如果 <paramref name="String" /> 是一个 <see langword="String" /> 表达式，则只将字符串的第一个字符用于输入。 如果 <paramref name="String" /> 是 <see langword="Nothing" /> 或不包含任何字符，将会出现 <see cref="T:System.ArgumentException" /> 错误。</param>
        /// <returns>与某个字符相对应的字符代码。</returns>
        public static int Asc(string String)
        {
            if (String == null || String.Length == 0)
                //throw new ArgumentException(Utils.GetResourceString("Argument_LengthGTZero1", new string[1]
                //{
                //    nameof (String)
                //}));
                throw new Exception("Asc Error");
            return Asc(String[0]);
        }

        /// <summary>使用 <paramref name="sDest" /> 参数的内容覆盖 <paramref name="sInsert" /> 参数。</summary>
        /// <param name="sDest">必需。 要修改的字符串变量。</param>
        /// <param name="StartPosition">必需。 要在 <paramref name="sDest" /> 参数中进行覆盖的起始位置。 索引从 1 开始。</param>
        /// <param name="MaxInsertLength">必需。 要从 <paramref name="sInsert" /> 参数中使用的最大字符数（从第一个字符开始算起）。</param>
        /// <param name="sInsert">必需。 用于覆盖 <paramref name="sDest" /> 参数的字符串值。</param>
        public static void MidStmtStr(ref string sDest, int StartPosition, int MaxInsertLength, string sInsert)
        {
            int length = 0;
            if (sDest != null)
                length = sDest.Length;
            int count1 = 0;
            if (sInsert != null)
                count1 = sInsert.Length;
            checked { --StartPosition; }
            if (StartPosition < 0 || StartPosition >= length)
                //throw new ArgumentException(Utils.GetResourceString("Argument_InvalidValue1", new string[1]
                //{
                //    "Start"
                //}));
                throw new Exception("MidStmtStr Error");
            if (MaxInsertLength < 0)
                //throw new ArgumentException(Utils.GetResourceString("Argument_InvalidValue1", new string[1]
                //{
                //    "Length"
                //}));
                throw new Exception("MidStmtStr Error");
            if (count1 > MaxInsertLength)
                count1 = MaxInsertLength;
            if (count1 > checked(length - StartPosition))
                count1 = checked(length - StartPosition);
            if (count1 == 0)
                return;
            StringBuilder stringBuilder = new StringBuilder(length);
            if (StartPosition > 0)
                stringBuilder.Append(sDest, 0, StartPosition);
            stringBuilder.Append(sInsert, 0, count1);
            int count2 = checked(length - StartPosition + count1);
            if (count2 > 0)
            {
                try
                {
                    stringBuilder.Append(sDest, checked(StartPosition + count1), count2);
                }                
                catch(Exception ex)
                {
                    throw ex;
                }
            }                
            sDest = stringBuilder.ToString();
        }

        /// <summary>返回一个包含字符串中的字符数或存储某个变量所需的名义字节数的整数。</summary>
        /// <param name="Expression">任何有效的 <see langword="String" /> 表达式或变量名。 如果 <paramref name="Expression" /> 为 <see langword="Object" /> 类型，<see langword="Len" /> 函数将返回其在由 <see langword="FilePut" /> 函数写入文件中时的大小。</param>
        /// <returns>一个包含字符串中的字符数或存储某个变量所需的名义字节数的整数。</returns>
        public static int Len(string Expression)
        {
            return Expression != null ? Expression.Length : 0;
        }
    }
}
