using System;
using Microsoft.SPOT;

namespace CPF
{
    // Construct a larger string by appending strings together.
    public class StringBuilder
    {
        private const int INITIAL_SIZE = 16;
        private const int MIN_GROWTH_SIZE = 64;

        private char[]  _content = null;
        private int     _currentLength = 0;

        public StringBuilder()
            : this(INITIAL_SIZE)
        {
        }

        public StringBuilder(int capacity)
        {
            this._content = new char[capacity];
        }

        public StringBuilder(string initial)
        {
            this._content = initial.ToCharArray();
            this._currentLength = _content.Length;
        }

        // Append a character to the current string builder
        public void Append(char c)
        {
            this.Append(new string(new char[] { c }));
        }

        // Append a string to the current string builder
        public void Append(string toAppend)
        {
            int additionalSpaceRequired = (toAppend.Length + _currentLength) - _content.Length;

            if (additionalSpaceRequired > 0)
            {
                // ensure at least minimum growth size is done to minimise future copying / manipulation
                if (additionalSpaceRequired < MIN_GROWTH_SIZE)
                {
                    additionalSpaceRequired = MIN_GROWTH_SIZE;
                }

                char[] tmp = new char[_content.Length + additionalSpaceRequired];

                // copy content to new array
                Array.Copy(_content, tmp, _currentLength);

                // replace the content array.
                _content = tmp;
            }

            // copy the new content to the holding array
            Array.Copy(toAppend.ToCharArray(), 0, _content, _currentLength, toAppend.Length);
            _currentLength += toAppend.Length;
        }

        // Append the provided line along with a new line.
        public void AppendLine(string str)
        {
            this.Append(str);
            this.Append("\r\n");
        }

        // Append to the string builder using format string and placeholder arguments
        public void AppendFormat(string format, params object[] args)
        {
            this.Append(StringUtility.Format(format, args));
        }

        // Clear the current string builder back to an empty string.
        public void Clear()
        {
            _currentLength = 0;
        }

        // Get the final built string.
        public override string ToString()
        {
            return new string(_content, 0, _currentLength);
        }
    }
}

