#if !USE_CUSTOM_VSTRING_SCRIPT
using System;
using System.Runtime.CompilerServices;
using UnityEngine;

namespace Giant.Common
{
    /// <summary>
    /// 无GC的字符串构造器，用以替代StringBuilder
    /// StringBuilder在处理float、int、bool等类型时会调用该类型对象的ToString()产生GC
    /// </summary>
    public class X2StringBuilder
    {
        protected X2StringBuilder() { }



        static X2StringBuilder()
        {
            s_CharBuffer = new char[16];
            s_Capacity = s_CharBuffer.Length;
            s_Length = 0;
        }



        private static char[] s_CharBuffer;



        private static int s_Capacity;



        private static int s_Length;
        public static int Length
        {
            get { return s_Length; }
        }



        public static void Append(string _Value)
        {
            if (string.IsNullOrEmpty(_Value)) return;
            int tValueLength = _Value.Length;
            int tRequiredLength = s_Length + tValueLength;
            if (NeedAllocation(tRequiredLength))
            {
                s_Capacity = Mathf.NextPowerOfTwo(tRequiredLength);
                Array.Resize(ref s_CharBuffer, s_Capacity);
            }
            for (int tIdx = 0; tIdx < tValueLength; tIdx++)
            {
                var tChar = _Value[tIdx];
                s_CharBuffer[s_Length++] = tChar;
                if (tChar == '\0')
                    return;
            }
            TryAppendStringTerminator();
        }



        /// <summary>
        /// 附加字符串并换行
        /// </summary>
        public static void AppendLine(string _Value)
        {
            Append(_Value);
            Append('\n');
        }



        /// <summary>
        /// 保留小数点后指定位数，截断后面的位数
        /// </summary>
        /// <param name="value"></param>
        /// <param name="decimalLength">小数点后位数</param>
        public static void Append(float value, int decimalLength = 5)
        {
            bool tIsNegative = (value < 0);
            if (tIsNegative)
                value = -value;
            uint tIntegerPart = (uint)Mathf.FloorToInt(value);
            if (tIsNegative)
                Append('-');
            Append(tIntegerPart);
            uint tDecimalPart = (uint)((value - tIntegerPart) * GetScaleFactor(decimalLength));
            if (tDecimalPart >= 1)
            {
                Append('.');
                Append(tDecimalPart);
            }
        }



        /// <summary>
        /// 获取保留小数点后指定位数所需的放大倍数
        /// </summary>
        /// <param name="decimalLength">保留小数点后指定位数</param>
        /// <returns>放大倍数</returns>
        private static uint GetScaleFactor(int decimalLength)
        {
            uint tScale = 1;
            if (decimalLength > 0)
            {
                for (int tIdx = 0; tIdx < decimalLength; tIdx++)
                    tScale *= 10;
            }
            return tScale;
        }



        public static void Append(int value)
        {
            bool tIsNegative = (value < 0);
            if (tIsNegative)
            {
                Append('-');
                value = -value;
            }

            Append((uint)value);
        }



        /// <summary>
        /// 附加字符串并换行
        /// </summary>
        public static void AppendLine(int _Value)
        {
            Append(_Value);
            Append('\n');
        }



        public static void Append(uint value)
        {
            int tValueLength = X2StringUtil.GetIntLength(value);
            int tRequiredLength = s_Length + tValueLength;
            if (NeedAllocation(tRequiredLength))
            {
                s_Capacity = Mathf.NextPowerOfTwo(tRequiredLength);
                Array.Resize(ref s_CharBuffer, s_Capacity);
            }

            unsafe
            {
                fixed (char* pDst = &s_CharBuffer[s_Length])
                {
                    for (int tIdx = tValueLength - 1; tIdx >= 0; --tIdx)
                    {
                        *(pDst + tIdx) = X2StringUtil.sNumerialChars[value % 10];
                        value = value / 10;
                    }
                    s_Length = tRequiredLength;
                }
                TryAppendStringTerminator();
            }
        }



        public static void Append(char value)
        {
            int tRequiredLength = s_Length + 1;
            if (NeedAllocation(tRequiredLength))
            {
                s_Capacity = Mathf.NextPowerOfTwo(tRequiredLength);
                Array.Resize(ref s_CharBuffer, s_Capacity);
            }
            s_CharBuffer[s_Length++] = value;
            TryAppendStringTerminator();
        }



        /// <summary>
        /// 尝试添加字符串结束符
        /// </summary>
        [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
        private static void TryAppendStringTerminator()
        {
            if (s_Length < s_Capacity)
                s_CharBuffer[s_Length] = '\0';
        }



        [MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
        private static bool NeedAllocation(int requiredLength)
        {
            return s_Capacity < requiredLength;
        }



        public static void Clear()
        {
            s_CharBuffer[0] = '\0';
            s_Length = 0;
        }



        public static void CopyToString(string _Dest)
        {
            if (_Dest == null) return;
            int tDstLen = _Dest.Length;
            if (tDstLen < s_Length) return;
            int tStrLen = s_Length;
            unsafe
            {
                fixed (char* pSrc = s_CharBuffer, pDest = _Dest)
                {
                    Buffer.wstrcpy(pDest, pSrc, tStrLen);
                    if(tDstLen > s_Length)
                        *(pDest + tStrLen) = '\0';
                }
            }
        }



        public static string ConvertToString()
        {
            return new string(s_CharBuffer, 0, Length);
        }
    }
}
#endif