// Copyright (c) 2024-2026 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.

// iterator.go
package kern

import (
	// "errors"
	"fmt"
	"slices"
)

// Operator names

const (
	InitName    = "init"
	CleanName   = "clean"
	ResetName   = "reset"
	NextName    = "next"
	CurrentName = "current"
	IndexName   = "index"
	CountName   = "count"
	FilterName  = "filter"
	MapName     = "map"
	KeyName     = "key"
	ValueName   = "value"
)

type Iterator interface {
	Typer
	fmt.Stringer
	Next() (item any, err error) // must return io.EOF after the last item
	Current() (item any, err error)
	Index() int64
	Count() int64
	HasOperation(name string) bool
	CallOperation(name string, args map[string]any) (value any, err error)
}

type ExtIterator interface {
	Iterator
	Reset() error
	Clean() error
}

func ErrNoOperation(name string) error {
	return fmt.Errorf("no %s() function defined in the data-source", name)
}

func IsIterator(v any) (ok bool) {
	_, ok = v.(Iterator)
	return
}

type IteratorBase struct {
	ItemIndex int64
	ItemCount int64
	current   any
}

func (it *IteratorBase) Current() (item any, err error) {
	return it.current, nil
}

func (it *IteratorBase) Index() int64 {
	return it.ItemIndex
}

func (it *IteratorBase) Count() int64 {
	return it.ItemCount
}

func (it *IteratorBase) HasOperation(name string) bool {
	return slices.Contains([]string{NextName, IndexName, CountName, CurrentName}, name)
}

func (it *IteratorBase) Clean() (err error) {
	return
}

func (it *IteratorBase) Reset() (err error) {
	it.ItemIndex = -1
	it.ItemCount = 0
	it.current = nil
	return
}

func (it *IteratorBase) Increment() {
	it.ItemIndex++
	it.ItemCount++
}

func (it *IteratorBase) SetCurrent(v any) {
	it.current = v
}
