using System;

namespace SWRIS.Models
{
    public class ByteCircularBuffer
    {
        private byte[] _buffer;
        private int _head;
        private int _tail;
        private int _count;
        private readonly object _lock = new object();

        public ByteCircularBuffer(int capacity)
        {
            _buffer = new byte[capacity];
        }

        public int Length => _count;

        public void Write(byte[] data, int offset, int count)
        {
            lock (_lock)
            {
                if (_count + count > _buffer.Length)
                {
                    // 自动扩容或丢弃旧数据
                    EnsureCapacity(_count + count);
                }

                for (int i = 0; i < count; i++)
                {
                    _buffer[_tail] = data[offset + i];
                    _tail = (_tail + 1) % _buffer.Length;
                }
                _count += count;
            }
        }

        public int Read(byte[] data, int offset, int count)
        {
            lock (_lock)
            {
                int bytesToRead = Math.Min(count, _count);
                for (int i = 0; i < bytesToRead; i++)
                {
                    data[offset + i] = _buffer[_head];
                    _head = (_head + 1) % _buffer.Length;
                }
                _count -= bytesToRead;
                return bytesToRead;
            }
        }

        public int Peek(byte[] data, int offset, int count)
        {
            lock (_lock)
            {
                int bytesToPeek = Math.Min(count, _count);
                int tempHead = _head;
                for (int i = 0; i < bytesToPeek; i++)
                {
                    data[offset + i] = _buffer[tempHead];
                    tempHead = (tempHead + 1) % _buffer.Length;
                }
                return bytesToPeek;
            }
        }

        public byte PeekByte(int offset = 0)
        {
            lock (_lock)
            {
                if (offset >= _count) return 0;
                return _buffer[(_head + offset) % _buffer.Length];
            }
        }

        private void EnsureCapacity(int requiredCapacity)
        {
            if (requiredCapacity <= _buffer.Length) return;

            int newCapacity = Math.Max(_buffer.Length * 2, requiredCapacity);
            byte[] newBuffer = new byte[newCapacity];

            if (_head <= _tail)
            {
                Buffer.BlockCopy(_buffer, _head, newBuffer, 0, _count);
            }
            else
            {
                int firstPart = _buffer.Length - _head;
                Buffer.BlockCopy(_buffer, _head, newBuffer, 0, firstPart);
                Buffer.BlockCopy(_buffer, 0, newBuffer, firstPart, _tail);
            }

            _buffer = newBuffer;
            _head = 0;
            _tail = _count;
        }

        public void Clear()
        {
            lock (_lock)
            {
                _head = _tail = _count = 0;
            }
        }

        public void Remove(int count)
        {
            lock (_lock)
            {
                int bytesToRemove = Math.Min(count, _count);
                _head = (_head + bytesToRemove) % _buffer.Length;
                _count -= bytesToRemove;
            }
        }
    }
}
