// 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/id"
	"code.forgejo.org/f3/gof3/v3/path"
)

func NodeCompare(ctx context.Context, a, b NodeInterface) bool {
	a.Trace("a '%s' | b '%s'", a.GetCurrentPath().ReadableString(), b.GetCurrentPath().ReadableString())

	if a.GetKind() != b.GetKind() {
		a.Trace("kind is different a = %s | b = %s", a.GetKind(), b.GetKind())
		return false
	}

	if diff := a.GetTree().Diff(a, b); diff != "" {
		a.Trace("difference %s", diff)
		return false
	}

	aChildren := a.GetNodeChildren()
	bChildren := b.GetNodeChildren()
	aLen := len(aChildren)
	bLen := len(bChildren)
	if aLen != bLen {
		a.Trace("children count is different a = %d | b = %d", aLen, bLen)
		return false
	}

	for aID, aChild := range aChildren {
		bID := aChild.GetID()
		mappedID := aChild.GetMappedID()
		if mappedID != id.NilID {
			bID = mappedID
		}
		bChild, ok := bChildren[bID]
		if !ok {
			a.Trace("there is no child in 'b' with id %s matching the child in 'a' with id %s", bID, aID)
			return false
		}

		if !NodeCompare(ctx, aChild, bChild) {
			return false
		}
	}

	return true
}

func TreeCompare(ctx context.Context, aTree TreeInterface, aPath path.Path, bTree TreeInterface, bPath path.Path) bool {
	aTree.Trace("'%s' => '%s'", aPath.ReadableString(), bPath.ReadableString())

	a := aTree.Find(aPath)
	if a == NilNode {
		aTree.Trace("a does not have %s", aPath.ReadableString())
		return false
	}

	b := bTree.Find(bPath)
	if b == NilNode {
		aTree.Trace("b does not have %s", bPath.ReadableString())
		return false
	}

	return NodeCompare(ctx, a, b)
}
