package iter

import (
	"github.com/andeya/gust"
)

var (
	_ gust.Iterable[any]    = (*IterableVec[any])(nil)
	_ gust.IterableSizeHint = (*IterableVec[any])(nil)
	_ gust.IterableCount    = (*IterableVec[any])(nil)
	_ gust.DeIterable[uint] = (*IterableVec[uint])(nil)
)

type IterableVec[T any] struct {
	slice         []T
	nextIndex     int
	backNextIndex int
}

func NewIterableVec[T any](slice []T) *IterableVec[T] {
	return &IterableVec[T]{
		slice:         slice,
		nextIndex:     0,
		backNextIndex: len(slice) - 1,
	}
}

func (v *IterableVec[T]) ToDeIterator() DeIterator[T] {
	return FromDeIterable[T](v)
}

func (v *IterableVec[T]) Next() gust.Option[T] {
	if v.nextIndex <= v.backNextIndex {
		opt := gust.Some(v.slice[v.nextIndex])
		v.nextIndex++
		return opt
	}
	return gust.None[T]()
}

func (v *IterableVec[T]) NextBack() gust.Option[T] {
	if v.backNextIndex >= 0 {
		opt := gust.Some(v.slice[v.backNextIndex])
		v.backNextIndex--
		return opt
	}
	return gust.None[T]()
}

func (v *IterableVec[T]) SizeHint() (uint, gust.Option[uint]) {
	if v.backNextIndex < 0 {
		return 0, gust.Some[uint](0)
	}
	n := uint(v.backNextIndex - v.nextIndex + 1)
	return n, gust.Some(n)
}

func (v *IterableVec[T]) Count() uint {
	if v.backNextIndex < 0 {
		return 0
	}
	count := uint(v.backNextIndex - v.nextIndex + 1)
	v.nextIndex = v.backNextIndex
	return count
}

func (v *IterableVec[T]) Remaining() uint {
	if v.backNextIndex < 0 {
		return 0
	}
	return uint(v.backNextIndex - v.nextIndex + 1)
}
