import { IArrayEnumerator } from '../../addons/enumerable-ts/src/index'

import { GArray } from 'godot'

type Nullable<T> = T | null | undefined

const DoneIteratorResult = Object.freeze({ value: undefined, done: true })

export class GArrayEnumerator<T> implements IArrayEnumerator<T>, Iterator<T>, Iterable<T> {
  private _array: GArray<T>
  private _index: number = -1

  get current(): Nullable<T> {
    return this._array.get_indexed(this._index)
  }

  constructor(array: GArray<T>) {
    this._array = array
  }

  [Symbol.iterator](): Iterator<T> {
    return this._array[Symbol.iterator]() as Iterator<T>
  }

  setIndex(index: number): void {
    this._index = index
  }

  moveNext(): boolean {
    this._index += 1
    return this._index < this._array.size()
  }

  reset(): void {
    this._index = -1
  }

  toIterator<T>(): Iterator<T> {
    return this._array[Symbol.iterator]() as Iterator<T>
  }

  next(...[_value]: [] | [any]): IteratorResult<T> {
    const next = this.moveNext()
    return { value: this.current, done: !next } as IteratorResult<T>
  }

  return?(_value?: any): IteratorResult<T, any> {
    return DoneIteratorResult
  }

  throw?(_e?: any): IteratorResult<T, any> {
    return DoneIteratorResult
  }
}

