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

package generic

import (
	"context"
	"errors"
	"fmt"

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

type NodeDriverInterface interface {
	logger.MessageInterface

	MapIDInterface

	IsNull() bool

	GetNode() NodeInterface
	SetNode(NodeInterface)

	SetTreeDriver(treeDriver TreeDriverInterface)
	GetTreeDriver() TreeDriverInterface

	ListPage(context.Context, int) ChildrenSlice
	GetIDFromName(context.Context, string) id.NodeID

	Equals(context.Context, NodeInterface) bool

	Get(context.Context) bool
	Put(context.Context) id.NodeID
	Patch(context.Context)
	Delete(context.Context)

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

	LookupMappedID(id.NodeID) id.NodeID

	String() string
}

type NullDriver struct {
	logger.Logger

	node       NodeInterface
	mapped     id.NodeID
	treeDriver TreeDriverInterface
}

func NewNullDriver() NodeDriverInterface {
	return &NullDriver{}
}

func (o *NullDriver) IsNull() bool               { return true }
func (o *NullDriver) SetNode(node NodeInterface) { o.node = node }
func (o *NullDriver) GetNode() NodeInterface     { return o.node }
func (o *NullDriver) GetMappedID() id.NodeID {
	if o.mapped == nil {
		return id.NilID
	}
	return o.mapped
}
func (o *NullDriver) SetMappedID(mapped id.NodeID) { o.mapped = mapped }
func (o *NullDriver) SetTreeDriver(treeDriver TreeDriverInterface) {
	o.treeDriver = treeDriver
	if treeDriver != nil {
		o.SetLogger(treeDriver)
	}
}
func (o *NullDriver) GetTreeDriver() TreeDriverInterface { return o.treeDriver }
func (o *NullDriver) ListPage(context.Context, int) ChildrenSlice {
	panic(fmt.Errorf("ListPage %s", o.GetNode().GetKind()))
}

func (o *NullDriver) GetIDFromName(ctx context.Context, name string) id.NodeID {
	panic(errors.New(name))
}

func (o *NullDriver) Equals(context.Context, NodeInterface) bool {
	panic(fmt.Errorf("Equals %s", o.GetNode().GetKind()))
}
func (o *NullDriver) Get(context.Context) bool { panic(fmt.Errorf("Get %s", o.GetNode().GetKind())) }
func (o *NullDriver) Put(context.Context) id.NodeID {
	panic(fmt.Errorf("Put %s", o.GetNode().GetKind()))
}

func (o *NullDriver) Patch(context.Context) {
	panic(fmt.Errorf("Patch %s", o.GetNode().GetKind()))
}
func (o *NullDriver) Delete(context.Context) { panic(fmt.Errorf("Delete %s", o.GetNode().GetKind())) }
func (o *NullDriver) NewFormat() f3.Interface {
	panic(fmt.Errorf("NewFormat %s", o.GetNode().GetKind()))
}

func (o *NullDriver) FromFormat(f3.Interface) {
	panic(fmt.Errorf("FromFormat %s", o.GetNode().GetKind()))
}
func (o *NullDriver) ToFormat() f3.Interface             { panic(fmt.Errorf("ToFormat %s", o.GetNode().GetKind())) }
func (o *NullDriver) LookupMappedID(id.NodeID) id.NodeID { return id.NilID }
func (o *NullDriver) String() string                     { return "" }
