// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package godoc

import (
	"bytes"
	"reflect"
	"sort"
	"strings"
	"testing"

	"golang.org/x/tools/godoc/vfs/mapfs"
)

func newCorpus(t *testing.T) *Corpus {
	c := NewCorpus(mapfs.New(map[string]string{
		"src/foo/foo.go": `// Package foo is an example.
package foo

import "bar"

const Pi = 3.1415

var Foos []Foo

// Foo is stuff.
type Foo struct{}

func New() *Foo {
   return new(Foo)
}
`,
		"src/bar/bar.go": `// Package bar is another example to test races.
package bar
`,
		"src/other/bar/bar.go": `// Package bar is another bar package.
package bar
func X() {}
`,
		"src/skip/skip.go": `// Package skip should be skipped.
package skip
func Skip() {}
`,
		"src/bar/readme.txt": `Whitelisted text file.
`,
		"src/bar/baz.zzz": `Text file not whitelisted.
`,
	}))
	c.IndexEnabled = true
	c.IndexDirectory = func(dir string) bool {
		return !strings.Contains(dir, "skip")
	}

	if err := c.Init(); err != nil {
		t.Fatal(err)
	}
	return c
}

func TestIndex(t *testing.T) {
	for _, docs := range []bool{true, false} {
		for _, goCode := range []bool{true, false} {
			for _, fullText := range []bool{true, false} {
				c := newCorpus(t)
				c.IndexDocs = docs
				c.IndexGoCode = goCode
				c.IndexFullText = fullText
				c.UpdateIndex()
				ix, _ := c.CurrentIndex()
				if ix == nil {
					t.Fatal("no index")
				}
				t.Logf("docs, goCode, fullText = %v,%v,%v", docs, goCode, fullText)
				testIndex(t, c, ix)
			}
		}
	}
}

func TestIndexWriteRead(t *testing.T) {
	type key struct {
		docs, goCode, fullText bool
	}
	type val struct {
		buf *bytes.Buffer
		c   *Corpus
	}
	m := map[key]val{}

	for _, docs := range []bool{true, false} {
		for _, goCode := range []bool{true, false} {
			for _, fullText := range []bool{true, false} {
				k := key{docs, goCode, fullText}
				c := newCorpus(t)
				c.IndexDocs = docs
				c.IndexGoCode = goCode
				c.IndexFullText = fullText
				c.UpdateIndex()
				ix, _ := c.CurrentIndex()
				if ix == nil {
					t.Fatal("no index")
				}
				var buf bytes.Buffer
				nw, err := ix.WriteTo(&buf)
				if err != nil {
					t.Fatalf("Index.WriteTo: %v", err)
				}
				m[k] = val{bytes.NewBuffer(buf.Bytes()), c}
				ix2 := new(Index)
				nr, err := ix2.ReadFrom(&buf)
				if err != nil {
					t.Fatalf("Index.ReadFrom: %v", err)
				}
				if nr != nw {
					t.Errorf("Wrote %d bytes to index but read %d", nw, nr)
				}
				testIndex(t, c, ix)
			}
		}
	}
	// Test CompatibleWith
	for k1, v1 := range m {
		ix := new(Index)
		if _, err := ix.ReadFrom(v1.buf); err != nil {
			t.Fatalf("Index.ReadFrom: %v", err)
		}
		for k2, v2 := range m {
			if got, want := ix.CompatibleWith(v2.c), k1 == k2; got != want {
				t.Errorf("CompatibleWith = %v; want %v for %v, %v", got, want, k1, k2)
			}
		}
	}
}

func testIndex(t *testing.T, c *Corpus, ix *Index) {
	if _, ok := ix.words["Skip"]; ok {
		t.Errorf("the word Skip was found; expected it to be skipped")
	}
	checkStats(t, c, ix)
	checkImportCount(t, c, ix)
	checkPackagePath(t, c, ix)
	checkExports(t, c, ix)
	checkIdents(t, c, ix)
}

// checkStats checks the Index's statistics.
// Some statistics are only set when we're indexing Go code.
func checkStats(t *testing.T, c *Corpus, ix *Index) {
	want := Statistics{}
	if c.IndexFullText {
		want.Bytes = 314
		want.Files = 4
		want.Lines = 21
	} else if c.IndexDocs || c.IndexGoCode {
		want.Bytes = 291
		want.Files = 3
		want.Lines = 20
	}
	if c.IndexGoCode {
		want.Words = 8
		want.Spots = 12
	}
	if got := ix.Stats(); !reflect.DeepEqual(got, want) {
		t.Errorf("Stats = %#v; want %#v", got, want)
	}
}

// checkImportCount checks the Index's import count map.
// It is only set when we're indexing Go code.
func checkImportCount(t *testing.T, c *Corpus, ix *Index) {
	want := map[string]int{}
	if c.IndexGoCode {
		want = map[string]int{
			"bar": 1,
		}
	}
	if got := ix.ImportCount(); !reflect.DeepEqual(got, want) {
		t.Errorf("ImportCount = %v; want %v", got, want)
	}
}

// checkPackagePath checks the Index's package path map.
// It is set if at least one of the indexing options is enabled.
func checkPackagePath(t *testing.T, c *Corpus, ix *Index) {
	want := map[string]map[string]bool{}
	if c.IndexDocs || c.IndexGoCode || c.IndexFullText {
		want = map[string]map[string]bool{
			"foo": map[string]bool{
				"foo": true,
			},
			"bar": map[string]bool{
				"bar":       true,
				"other/bar": true,
			},
		}
	}
	if got := ix.PackagePath(); !reflect.DeepEqual(got, want) {
		t.Errorf("PackagePath = %v; want %v", got, want)
	}
}

// checkExports checks the Index's exports map.
// It is only set when we're indexing Go code.
func checkExports(t *testing.T, c *Corpus, ix *Index) {
	want := map[string]map[string]SpotKind{}
	if c.IndexGoCode {
		want = map[string]map[string]SpotKind{
			"foo": map[string]SpotKind{
				"Pi":   ConstDecl,
				"Foos": VarDecl,
				"Foo":  TypeDecl,
				"New":  FuncDecl,
			},
			"other/bar": map[string]SpotKind{
				"X": FuncDecl,
			},
		}
	}
	if got := ix.Exports(); !reflect.DeepEqual(got, want) {
		t.Errorf("Exports = %v; want %v", got, want)
	}
}

// checkIdents checks the Index's indents map.
// It is only set when we're indexing documentation.
func checkIdents(t *testing.T, c *Corpus, ix *Index) {
	want := map[SpotKind]map[string][]Ident{}
	if c.IndexDocs {
		want = map[SpotKind]map[string][]Ident{
			PackageClause: map[string][]Ident{
				"bar": []Ident{
					{"bar", "bar", "bar", "Package bar is another example to test races."},
					{"other/bar", "bar", "bar", "Package bar is another bar package."},
				},
				"foo":   []Ident{{"foo", "foo", "foo", "Package foo is an example."}},
				"other": []Ident{{"other/bar", "bar", "bar", "Package bar is another bar package."}},
			},
			ConstDecl: map[string][]Ident{
				"Pi": []Ident{{"foo", "foo", "Pi", ""}},
			},
			VarDecl: map[string][]Ident{
				"Foos": []Ident{{"foo", "foo", "Foos", ""}},
			},
			TypeDecl: map[string][]Ident{
				"Foo": []Ident{{"foo", "foo", "Foo", "Foo is stuff."}},
			},
			FuncDecl: map[string][]Ident{
				"New": []Ident{{"foo", "foo", "New", ""}},
				"X":   []Ident{{"other/bar", "bar", "X", ""}},
			},
		}
	}
	if got := ix.Idents(); !reflect.DeepEqual(got, want) {
		t.Errorf("Idents = %v; want %v", got, want)
	}
}

func TestIdentResultSort(t *testing.T) {
	ic := map[string]int{
		"/a/b/pkg1": 10,
		"/a/b/pkg2": 2,
		"/b/d/pkg3": 20,
	}
	for _, tc := range []struct {
		ir  []Ident
		exp []Ident
	}{
		{
			ir: []Ident{
				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
			},
			exp: []Ident{
				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
			},
		},
		{
			ir: []Ident{
				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
			},
			exp: []Ident{
				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
				{"/a/a/pkg1", "pkg1", "MyFunc1", ""},
			},
		},
	} {
		if sort.Sort(byImportCount{tc.ir, ic}); !reflect.DeepEqual(tc.ir, tc.exp) {
			t.Errorf("got: %v, want %v", tc.ir, tc.exp)
		}
	}
}

func TestIdentFilter(t *testing.T) {
	ic := map[string]int{}
	for _, tc := range []struct {
		ir  []Ident
		pak string
		exp []Ident
	}{
		{
			ir: []Ident{
				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
				{"/b/d/pkg3", "pkg3", "MyFunc3", ""},
				{"/a/b/pkg1", "pkg1", "MyFunc1", ""},
			},
			pak: "pkg2",
			exp: []Ident{
				{"/a/b/pkg2", "pkg2", "MyFunc2", ""},
			},
		},
	} {
		res := byImportCount{tc.ir, ic}.filter(tc.pak)
		if !reflect.DeepEqual(res, tc.exp) {
			t.Errorf("got: %v, want %v", res, tc.exp)
		}
	}
}
