package zord_tree

import (
	cp "github.com/otiai10/copy"
	"io/ioutil"
	"os"
	"strings"
	"testing"
)

func prepare(t *testing.T) {
	err := os.Remove("./testdata/sunny1")
	if err != nil {
	}
	err = os.Remove("./testdata/sunny2")
	if err != nil {
	}
	err = cp.Copy("./testdata/sunny", "./testdata/sunny1")
	if err != nil {
		t.Fatal("Couldn't prepare data for testing")
	}
}

func TestFromNotExistingDirectory(t *testing.T) {
	_, err := BuildTree("./testing/i_dont_exist", []string{})
	if err == nil {
		t.Error("Not existing directory should return error, got NIL.")
	}
}

func TestSunny(t *testing.T) {
	prepare(t)

	tree, err := BuildTree("./testdata/sunny1", []string{})
	if err != nil {
		t.Errorf("Got error: %v", err)
	}

	if len(tree.Dirs) != 1 {
		t.Errorf("Should be 1 subdirectory, got %v", len(tree.Dirs))
	}

	if tree.Dirs[0].Files[0].Name != "file3.md" {
		t.Errorf("File should be 'file3.md', got %v", tree.Dirs[0].Files[0].Name)
	}
	if tree.Files[0].Name != "file1.md" {
		t.Errorf("File should be 'file1.md', got %v", tree.Files[0].Name)
	}
	if len(tree.Files[0].Tags) != 2 {
		t.Errorf("File 'file1.md' should have 2 tags, got %v", len(tree.Files[0].Tags))
	}
	if tree.Files[0].Tags[1] != "t2" {
		t.Errorf("File 'file1.md' 2nd tag 't2', got %v", tree.Files[0].Tags[1])
	}
	t.Log(tree)
}

func TestFixFormat(t *testing.T) {
	prepare(t)

	err := PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{}, nil)
	if err != nil {
		t.Fatal("Population ended in err:", err)
	}

	b, err := ioutil.ReadFile("./testdata/sunny2/file1.md")
	if err != nil {
		t.Fatal("No destination file 'file1.md'.")
	}
	str := string(b)
	t.Log(str)
	if !strings.Contains(str, "* tags: t1,t2\n* description: Če test file __va__\n") {
		t.Fatal("Empty lines has not been removed in file 'file1.md'.")
	}
	if !strings.Contains(str, "\n\n---\n") {
		t.Fatal("Split line has not been formatted in file 'file1.md'.")
	}
}

func TestMeta(t *testing.T) {
	prepare(t)

	meta := []string{"option1", "option2"}
	tree, err := BuildTree("./testdata/sunny1", meta)

	if err != nil {
		t.Errorf("Got error: %v", err)
	}

	if tree.Files[0].Name != "file1.md" {
		t.Errorf("File should be 'file1.md', got %v", tree.Files[0].Name)
	}

	if tree.Files[0].Meta["option1"] != "test option" {
		t.Error("File 'file1.md' should have 'option1' with value 'test option'")
	}
}

func TestId(t *testing.T) {
	prepare(t)

	err := PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{}, nil)
	if err != nil {
		t.Fatal("Population ended in err:", err)
	}

	b, err := ioutil.ReadFile("./testdata/sunny2/file1.md")
	if err != nil {
		t.Fatal("No destination file 'file1.md'.")
	}
	str := string(b)
	if !strings.Contains(str, "\n* id: 1\n") {
		t.Fatal("No id in file 'file1.md'.")
	}

	b, err = ioutil.ReadFile("./testdata/sunny2/subcategory/file3.md")
	if err != nil {
		t.Fatal("No destination file 'substring/file3.md'.")
	}
	str = string(b)
	if !strings.Contains(str, "\n* id: 3\n") {
		t.Fatal("No id in file 'file3.md'.")
	}
}

func TestMissingOptions(t *testing.T) {
	prepare(t)

	customMeta := make(map[string]func() string)
	customMeta["option2"] = func() string {
		return "customDefaultValue"
	}
	err := PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{"option1", "option2"}, customMeta)
	if err != nil {
		t.Fatal("Population ended in err:", err)
	}

	b, err := ioutil.ReadFile("./testdata/sunny2/file1.md")
	if err != nil {
		t.Fatal("No destination file 'file1.md'.")
	}
	str := string(b)
	if !strings.Contains(str, "\n* option1: test option\n") {
		t.Fatal("Changed old value for 'option1' in file 'file1.md'.")
	}
	if !strings.Contains(str, "\n* option2: customDefaultValue\n") {
		t.Fatal("'option2' has not been added to file 'file1.md'.")
	}

	b, err = ioutil.ReadFile("./testdata/sunny2/file2.md")
	if err != nil {
		t.Fatal("No destination file 'file2.md'.")
	}
	str = string(b)
	if !strings.Contains(str, "\n* option1: \n") {
		t.Fatal("'option1' has not been added to file 'file2.md'.")
	}
	if !strings.Contains(str, "\n* option2: customDefaultValue\n") {
		t.Fatal("'option2' has not been added to file 'file2.md'.")
	}

	b, err = ioutil.ReadFile("./testdata/sunny2/subcategory/file3.md")
	if err != nil {
		t.Fatal("No destination file 'substring/file3.md'.")
	}
	str = string(b)
	if !strings.Contains(str, "\n* option1: \n") {
		t.Fatal("'option1' has not been added to file 'file3.md'.")
	}
	if !strings.Contains(str, "\n* option2: it exists\n") {
		t.Fatal("Changed old value for 'option2' in file 'file3.md'.")
	}
}

func TestReadingFileContent(t *testing.T) {
	prepare(t)

	tree, err := BuildTree("./testdata/sunny1", []string{})

	if err != nil {
		t.Errorf("Got error: %v", err)
	}

	if tree.Files[0].Name != "file1.md" {
		t.Errorf("File should be 'file1.md', got %v", tree.Files[0].Name)
	}

	content, _ := ReadFileContent(tree.Files[0])
	if content != "# Če kažkas torietom būtė\n\n* lists\n\n__va__" {
		t.Error("File content is wrong...")
	}
}

func TestGetSlice(t *testing.T) {
	prepare(t)

	err := PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{}, nil)
	if err != nil {
		t.Fatal("Population ended in err:", err)
	}

	tree, err := BuildTree("./testdata/sunny2", []string{})
	if err != nil {
		t.Errorf("Got error: %v", err)
	}

	tree2, err := tree.Slice("testdata/sunny2/subcategory")
	if err != nil {
		t.Errorf("Error during search the tree: %v", err)
	}
	if tree2.Files[0].Name != "file3.md" {
		t.Errorf("Got frong tree")
	}
}

func TestGetFileById(t *testing.T) {
	prepare(t)

	err := PopulateTree("./testdata/sunny1", "./testdata/sunny2", []string{}, nil)
	if err != nil {
		t.Fatal("Population ended in err:", err)
	}

	tree, err := BuildTree("./testdata/sunny2", []string{})
	if err != nil {
		t.Errorf("Got error: %v", err)
	}

	file, err := tree.FileById("3")
	if err != nil {
		t.Errorf("Error during search: %v", err)
	}
	if file.Name != "file3.md" {
		t.Errorf("Got frong file: %s", file.Name)
	}
}