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

// data-cursors.go
package expr

import (
	"io"
)

const (
	initName    = "init"
	nextName    = "next"
	currentName = "current"
)

type dataCursor struct {
	ds          map[any]*term
	ctx         ExprContext
	index       int
	resource    any
	nextFunc    Functor
	currentFunc Functor
}

func newDataCursor(ctx ExprContext) (dc *dataCursor) {
	dc = &dataCursor{
		index: -1,
		ctx:   ctx.Clone(),
	}
	return
}

func (dc *dataCursor) String() string {
	return "$(...)"
}

func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
	ctx := cloneContext(dc.ctx)
	if item, err = dc.currentFunc.Invoke(ctx, currentName, []any{}); err == nil && item == nil {
		err = io.EOF
	}
	exportObjects(dc.ctx, ctx)
	return
}

func (dc *dataCursor) Next() (item any, err error) { // must return io.EOF after the last item
	ctx := cloneContext(dc.ctx)
	if item, err = dc.nextFunc.Invoke(ctx, nextName, []any{}); err == nil {
		if item == nil {
			err = io.EOF
		} else {
			dc.index++
		}
	}
	exportObjects(dc.ctx, ctx)
	return
}

func (dc *dataCursor) Index() int {
	return dc.index
}