package chezmoi

import (
	"errors"
	"testing"

	"github.com/alecthomas/assert/v2"
)

func TestSourceStateEntryTreeNodeEmpty(t *testing.T) {
	n := NewSourceStateEntryTreeNode()
	assert.Equal(t, nil, n.Get(EmptyRelPath))
	assert.Equal(t, []*SourceStateEntryTreeNode{n}, n.GetNodes(EmptyRelPath))
	assert.NoError(t, n.ForEach(EmptyRelPath, func(RelPath, SourceStateEntry) error {
		return errors.New("should not be called")
	}))
}

func TestSourceStateEntryTreeNodeSingle(t *testing.T) {
	n := NewSourceStateEntryTreeNode()
	sourceStateFile := &SourceStateFile{}
	n.Set(NewRelPath("file"), sourceStateFile)
	assert.Equal(t, sourceStateFile, n.Get(NewRelPath("file")).(*SourceStateFile))
	err := n.ForEach(EmptyRelPath, func(targetRelPath RelPath, sourceStateEntry SourceStateEntry) error {
		assert.Equal(t, NewRelPath("file"), targetRelPath)
		assert.Equal(t, sourceStateFile, sourceStateEntry.(*SourceStateFile))
		return nil
	})
	assert.NoError(t, err)
}

func TestSourceStateEntryTreeNodeMultiple(t *testing.T) {
	entries := map[RelPath]SourceStateEntry{
		NewRelPath("a_file"):     &SourceStateFile{},
		NewRelPath("b_file"):     &SourceStateFile{},
		NewRelPath("c_file"):     &SourceStateFile{},
		NewRelPath("dir"):        &SourceStateDir{},
		NewRelPath("dir/a_file"): &SourceStateFile{},
		NewRelPath("dir/b_file"): &SourceStateFile{},
	}
	n := NewSourceStateEntryTreeNode()
	for targetRelPath, sourceStateEntry := range entries {
		n.Set(targetRelPath, sourceStateEntry)
	}

	var targetRelPaths []RelPath
	err := n.ForEach(EmptyRelPath, func(targetRelPath RelPath, sourceStateEntry SourceStateEntry) error {
		assert.Equal(t, entries[targetRelPath], sourceStateEntry)
		targetRelPaths = append(targetRelPaths, targetRelPath)
		return nil
	})
	assert.NoError(t, err)
	assert.Equal(t, []RelPath{
		NewRelPath("a_file"),
		NewRelPath("b_file"),
		NewRelPath("c_file"),
		NewRelPath("dir"),
		NewRelPath("dir/a_file"),
		NewRelPath("dir/b_file"),
	}, targetRelPaths)

	assert.Equal(t, entries, n.GetMap())
}
