using System.Collections;
namespace ParadoxSaveParser.Lib;
///
/// Enumerator wrapper that stores N/2 items before and N/2-1 after Current item.
///
///
/// IEnumerator<int> Enumerator()
/// {
/// for(int i = 0; i < 6; i++)
/// yield return i;
/// }
///
/// var en = Enumerator();
/// var bufen = new BufferedEnumerator<int>(en, 5);
///
/// while(bufen.MoveNext())
/// {
/// var cur = bufen.Current;
/// for (var prev = cur.List?.First; prev != cur; prev = prev?.Next)
/// Console.Write($"{prev?.Value} ");
///
/// Console.Write($"| {cur.Value} |");
///
/// for (var next = cur.Next; next is not null; next = next.Next)
/// Console.Write($" {next.Value}");
/// Console.WriteLine();
/// }
///
/// Output:
///
/// | 0 | 1 2 3 4
/// 0 | 1 | 2 3 4
/// 0 1 | 2 | 3 4
/// 1 2 | 3 | 4 5
/// 2 3 | 4 | 5
/// 3 4 | 5 |
///
public class BufferedEnumerator : IEnumerator.Node>
{
public class Node
{
#nullable disable
public Node Previous;
public Node Next;
public T Value;
#nullable enable
}
private readonly IEnumerator _enumerator;
private readonly Node[] _ringBuffer;
private Node? _currentNode;
private int _currentBufferIndex = -1;
private int _lastValueIndex = -1;
public BufferedEnumerator(IEnumerator enumerator, int bufferSize)
{
_enumerator = enumerator;
_ringBuffer = new Node[bufferSize];
}
private void InitBuffer()
{
_ringBuffer[0] = new Node
{
Value = default!
};
for (int i = 1; i < _ringBuffer.Length; i++)
{
_ringBuffer[i] = new Node
{
Previous = _ringBuffer[i - 1],
Value = default!,
};
_ringBuffer[i - 1].Next = _ringBuffer[i];
}
_ringBuffer[^1].Next = _ringBuffer[0];
_ringBuffer[0].Previous = _ringBuffer[^1];
}
public bool MoveNext()
{
if (_currentBufferIndex == -1)
{
InitBuffer();
int beforeMidpoint = _ringBuffer.Length / 2 - 1;
for (int i = 0; i <= beforeMidpoint && _enumerator.MoveNext(); i++)
{
_ringBuffer[i].Value = _enumerator.Current;
}
}
_currentBufferIndex = (_currentBufferIndex + 1) % _ringBuffer.Length;
if (_enumerator.MoveNext())
{
int midpoint = (_currentBufferIndex + _ringBuffer.Length / 2) % _ringBuffer.Length;
_ringBuffer[midpoint].Value = _enumerator.Current;
_lastValueIndex = midpoint;
}
if(_currentBufferIndex == (_lastValueIndex + 1) % _ringBuffer.Length)
return false;
_currentNode = _ringBuffer[_currentBufferIndex];
return true;
}
public void Reset()
{
throw new NotImplementedException();
}
public Node Current => _currentNode!;
object IEnumerator.Current => Current;
public void Dispose()
{
}
}