// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT

package generic

import (
	"context"

	"code.forgejo.org/f3/gof3/v3/f3"
	"code.forgejo.org/f3/gof3/v3/id"
	"code.forgejo.org/f3/gof3/v3/kind"
	"code.forgejo.org/f3/gof3/v3/logger"
	"code.forgejo.org/f3/gof3/v3/path"
)

type NodeAccessorsInterface interface {
	SetIsNil(bool)
	GetIsNil() bool

	SetIsSync(bool)
	GetIsSync() bool

	GetParent() NodeInterface
	SetParent(NodeInterface)

	GetKind() kind.Kind
	SetKind(kind.Kind)

	GetID() id.NodeID
	SetID(id.NodeID)

	GetTree() TreeInterface
	SetTree(TreeInterface)

	GetNodeChildren() NodeChildren
	GetChildren() ChildrenSlice
	SetChildren(NodeChildren)

	GetDriver() NodeDriverInterface
	SetDriver(NodeDriverInterface)
}

type NodeTreeInterface interface {
	GetChild(id.NodeID) NodeInterface
	GetIDFromName(context.Context, string) id.NodeID
	SetChild(NodeInterface) NodeInterface
	DeleteChild(id.NodeID) NodeInterface
	CreateChild(context.Context) NodeInterface

	MustFind(path.Path) NodeInterface
	Find(path.Path) NodeInterface
	FindAndGet(context.Context, path.Path) NodeInterface

	GetCurrentPath() path.Path

	Walk(ctx context.Context, parent path.Path, options *WalkOptions)
	WalkAndGet(ctx context.Context, parent path.Path, options *WalkOptions)
	Apply(ctx context.Context, parent, path path.Path, options *ApplyOptions) bool
	ApplyAndGet(ctx context.Context, path path.Path, options *ApplyOptions) bool

	List(context.Context) ChildrenSlice
}

type NodeDriverProxyInterface interface {
	MapIDInterface
	ListPage(context.Context, int) ChildrenSlice
	GetIDFromName(context.Context, string) id.NodeID

	Equals(context.Context, NodeInterface) bool

	Get(context.Context) NodeInterface
	Upsert(context.Context) NodeInterface
	Delete(context.Context) NodeInterface

	NewFormat() f3.Interface
	FromFormat(f3.Interface) NodeInterface
	ToFormat() f3.Interface

	LookupMappedID(id.NodeID) id.NodeID
}

type MapIDInterface interface {
	GetMappedID() id.NodeID
	SetMappedID(id.NodeID)
}

type NodeInterface interface {
	logger.MessageInterface
	NodeAccessorsInterface
	NodeTreeInterface
	NodeDriverProxyInterface
	path.PathElement

	Init(NodeInterface) NodeInterface

	GetSelf() NodeInterface
	SetSelf(NodeInterface)

	String() string
}
