using System;
using System.Collections.Generic;
using System.Text;

namespace Apewer
{

    /// <summary>数组构建器。</summary>
    public sealed class ArrayBuilder<T>
    {

        private T[] _array;
        private int _capacity;
        private int _count;
        private int _step;

        /// <summary>创建构建程序实例。</summary>
        /// <param name="step">每次扩容的增量,最小值:1,默认值:256。</param>
        /// <exception cref="ArgumentNullException"></exception>
        public ArrayBuilder(int step = 256)
        {
            if (step < 1) throw new ArgumentOutOfRangeException(nameof(step));
            _step = step;
            _capacity = step;
            _count = 0;
            _array = new T[step];
        }

        private ArrayBuilder(ArrayBuilder<T> old)
        {
            _step = old._step;
            _capacity = old._capacity;
            _count = old._count;
            _array = new T[_capacity];
            if (_count > 0) Array.Copy(old._array, _array, _count);
        }

        /// <summary>获取或设置指定位置的元素,索引器范围为 [0, Length)。</summary>
        /// <exception cref="ArgumentOutOfRangeException"></exception>
        public T this[int index]
        {
            get
            {
                if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
                return _array[index];
            }
            set
            {
                if (index < 0 || index >= _count) throw new ArgumentOutOfRangeException("索引超出了当前数组的范围。");
                _array[index] = value;
            }
        }

        /// <summary>缓冲区的容量。</summary>
        public int Capacity { get => _capacity; }

        /// <summary>当前的元素数量。</summary>
        public int Length { get => _count; }

        /// <summary>当前的元素数量。</summary>
        public int Count { get => _count; }

        /// <summary>添加元素。</summary>
        public void Add(T item)
        {
            if (_count >= _capacity)
            {
                var capacity = _capacity + _step;
                var array = new T[capacity];
                Array.Copy(_array, array, _count);
                _array = array;
            }
            _array[_count] = item;
            _count++;
        }

        /// <summary>添加多个元素。</summary>
        public void Add(params T[] items)
        {
            if (items == null) return;

            var length = items.Length;
            if (length < 1) return;

            if (_capacity - _count < length)
            {
                _capacity = _count + length;
                var temp = new T[_capacity];
                Array.Copy(_array, temp, _count);
                _array = temp;
            }

            Array.Copy(items, _array, length);
            _count += length;
        }

        /// <summary>添加多个元素。</summary>
        public void Add(ICollection<T> items)
        {
            if (items == null) return;

            var length = items.Count;
            if (length < 1) return;

            if (_capacity - _count < length)
            {
                _capacity = _count + length;
                var temp = new T[_capacity];
                Array.Copy(_array, temp, _count);
                _array = temp;
            }

            items.CopyTo(_array, _count);
            _count += length;
        }

        /// <summary>添加多个元素。</summary>
        public void Add(IEnumerable<T> items)
        {
            if (items == null) return;
            foreach (var item in items) Add(item);
        }

        /// <summary>清空所有元素。</summary>
        public void Clear()
        {
            _capacity = 0;
            _count = 0;
            _array = new T[0];
        }

        // 修剪数组,去除剩余空间。
        void Trim()
        {
            if (_count == 0)
            {
                if (_capacity > 0)
                {
                    _capacity = 0;
                    _array = new T[0];
                }
                return;
            }

            if (_count == _capacity) return;

            var array = new T[_count];
            Array.Copy(_array, array, _count);
            _capacity = _count;
        }

        /// <summary></summary>
        /// <param name="clear"></param>
        /// <returns></returns>
        public T[] Export(bool clear = false)
        {
            if (_count == 0) return new T[0];
            if (_count == _capacity) return _array;
            var array = new T[_count];
            Array.Copy(_array, array, _count);
            return array;
        }

        /// <summary>克隆当前实例,生成新实例。</summary>
        public ArrayBuilder<T> Clone() => new ArrayBuilder<T>(this);

        /// <summary>使用 Export 方法实现从 ArrayBuilder&lt;T&gt; 到 T[] 的隐式转换。</summary>
        public static implicit operator T[](ArrayBuilder<T> instance) => instance == null ? null : instance.Export();

    }

}