package main

import (
	"testing"
)

func assertError(t testing.TB, got, want error) {
	t.Helper()
	if got != want {
		t.Errorf("got error %q want %q", got, want)
	}
}

func assertStrings(t testing.TB, got, want string) {
	t.Helper()
	if got != want {
		t.Errorf("got %q want %q give %q", got, want, "test")
	}
}

func TestSearch(t *testing.T) {
	searchStr := "this is just a test"
	// dictionary := map[string]string{"test": searchStr}
	// use our own type
	dictionary := Dictionary{"test": searchStr}

	t.Run("known word", func(t *testing.T) {
		got, _ := dictionary.Search("test")
		want := searchStr

		assertStrings(t, got, want)
	})

	t.Run("unknown word", func(t *testing.T) {
		_, err := dictionary.Search("not-test")

		assertError(t, err, ErrNotFound)

		// testing for an error's string is crude since error str can be modified
		// see README.md pointers_errors directory
		assertStrings(t, err.Error(), ErrNotFound.Error())
	})

}

func TestAdd(t *testing.T) {

	t.Run("new word", func(t *testing.T) {
		dictionary := Dictionary{}
		word := "test"
		definition := "this is just a test"

		dictionary.Add(word, definition)

		assertDefinition(t, dictionary, word, definition)

	})

	t.Run("new word", func(t *testing.T) {
		word := "test"
		definition := "this is just a test"
		dictionary := Dictionary{word: definition}

		err := dictionary.Add(word, definition)

		assertError(t, err, ErrWordExists)
		assertDefinition(t, dictionary, word, definition)
	})

}

func assertDefinition(t testing.TB, dictionary Dictionary, word, definition string) {
	t.Helper()

	got, err := dictionary.Search(word)
	if err != nil {
		t.Fatal("should find added word:", err)
	}
	assertStrings(t, got, definition)

}

func TestUpdate(t *testing.T) {
	updateStr := "Don't build the Torment Nexus!"

	t.Run("update works", func(t *testing.T) {
		dictionary := Dictionary{"test": "this is just a test"}

		dictionary.Update("test", updateStr)

		assertDefinition(t, dictionary, "test", updateStr)
	})

	t.Run("key does not exist", func(t *testing.T) {
		dictionary := Dictionary{}

		err := dictionary.Update("test", updateStr)

		assertError(t, err, ErrWordDoesNotExist)
	})
}

func TestDelete(t *testing.T) {
	dictionary := Dictionary{"test": "Don't build the Torment Nexus!"}

	dictionary.Delete("test")

	_, err := dictionary.Search("test")

	assertError(t, err, ErrNotFound)
}