class_name BoundedRangeIterator extends Iterator

var _range: IntRange
var _bounds: IntRange
var _count: int
var _step: int
var _items_yielded: int = 0

func _init(range: IntRange, bounds: IntRange, step: int = 1) -> void:
    self._range = range
    self._count = range.length()
    self._bounds = bounds
    self._step = step

static func from_array(xs: Array, iteration_range: IntRange, step: int = 1) -> BoundedRangeIterator:
    return BoundedRangeIterator.new(iteration_range, IntRange.new(0, len(xs)), step)

func _to_string() -> String:
    return "BoundedRangeIterator { range: %s, count: %s, bounds: %s, step: %s, items_yielded: %s }" % \
           [_range, _count, _bounds, _step, _items_yielded]

func clone() -> BoundedRangeIterator:
    var iter = BoundedRangeIterator.new(_range, _bounds, _step)
    iter._items_yielded = _items_yielded
    return iter

func next() -> Option:
    if _items_yielded >= _count:
        return Option.none

    var index = _range.min + (_items_yielded * _step)
    var wrapped_index = _bounds.wrap(index)
    _items_yielded += 1

    return Option.some(wrapped_index)
