namespace Universal;

public class RingBuffer<T>(int size)
{
    private readonly T[] _BufferArea = new T[size];
    private readonly int max = size - 1;

    int _startIndex = 0;
    int _endIndex = 0;
    bool _full = false;

    public void Insert(T content)
    {
        lock (this)
        {
            _BufferArea[_endIndex] = content;

            _endIndex = _endIndex == max ? 0 : _endIndex + 1;

            if (_endIndex == _startIndex)
            {
                _full = true;
                _startIndex = _startIndex == max ? 0 : _startIndex + 1;
            }
        }
    }

    private int LastStartIndex
    {
        get
        {
            if (!_full)
                return 0;

            if (_startIndex == 0)
                return max;

            return _startIndex - 1;
        }
    }

    private int LastEndIndex
    {
        get
        {
            if (_endIndex == 0)
                return max;

            return _endIndex - 1;
        }
    }

    public T[] ReadValues()
    {
        if (!_full)
            return _BufferArea[0.._endIndex];

        if (LastEndIndex > LastStartIndex)
            return _BufferArea;

        List<T> result = [];
        result.AddRange(_BufferArea[(LastEndIndex + 1)..]);
        result.AddRange(_BufferArea[0..LastStartIndex]);

        return [.. result];
    }


    public void Clear()
    {
        lock (this)
        {
            this._startIndex = 0;
            this._endIndex = 0;
            this._full = false;
        }
    }

}
