// Copyright 2019 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 cmd_test

import (
	"flag"
	"io/ioutil"
	"os"
	"strings"
	"testing"

	"golang.org/x/tools/go/packages/packagestest"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/span"
)

// We hardcode the expected number of test cases to ensure that all tests
// are being executed. If a test is added, this number must be changed.
const (
	expectedCompletionsCount = 64
	expectedDiagnosticsCount = 16
	expectedFormatCount      = 4
)

var internalPipe = flag.Bool("pipe", false, "connect the command line client to a server through a pipe")

func TestCommandLine(t *testing.T) {
	packagestest.TestAll(t, testCommandLine)
}

func testCommandLine(t *testing.T, exporter packagestest.Exporter) {
	const dir = "../testdata"

	files := packagestest.MustCopyFileTree(dir)
	for fragment, operation := range files {
		if trimmed := strings.TrimSuffix(fragment, ".in"); trimmed != fragment {
			delete(files, fragment)
			files[trimmed] = operation
		}
	}
	modules := []packagestest.Module{
		{
			Name:  "golang.org/x/tools/internal/lsp",
			Files: files,
		},
	}
	exported := packagestest.Export(t, exporter, modules)
	defer exported.Cleanup()

	// Do a first pass to collect special markers for completion.
	if err := exported.Expect(map[string]interface{}{
		"item": func(name string, r packagestest.Range, _, _ string) {
			exported.Mark(name, r)
		},
	}); err != nil {
		t.Fatal(err)
	}

	expectedDiagnostics := make(diagnostics)
	completionItems := make(completionItems)
	expectedCompletions := make(completions)
	expectedFormat := make(formats)
	expectedDefinitions := make(definitions)
	expectedTypeDefinitions := make(definitions)

	// Collect any data that needs to be used by subsequent tests.
	if err := exported.Expect(map[string]interface{}{
		"diag":       expectedDiagnostics.collect,
		"item":       completionItems.collect,
		"complete":   expectedCompletions.collect,
		"format":     expectedFormat.collect,
		"godef":      expectedDefinitions.godef,
		"definition": expectedDefinitions.definition,
		"typdef":     expectedTypeDefinitions.typdef,
	}); err != nil {
		t.Fatal(err)
	}

	t.Run("Completion", func(t *testing.T) {
		t.Helper()
		expectedCompletions.test(t, exported, completionItems)
	})

	t.Run("Diagnostics", func(t *testing.T) {
		t.Helper()
		expectedDiagnostics.test(t, exported)
	})

	t.Run("Format", func(t *testing.T) {
		t.Helper()
		expectedFormat.test(t, exported)
	})

	t.Run("Definitions", func(t *testing.T) {
		t.Helper()
		expectedDefinitions.testDefinitions(t, exported)
	})

	t.Run("TypeDefinitions", func(t *testing.T) {
		t.Helper()
		expectedTypeDefinitions.testTypeDefinitions(t, exported)
	})
}

type completionItems map[span.Range]*source.CompletionItem
type completions map[span.Span][]span.Span
type formats map[span.URI]span.Span

func (l completionItems) collect(spn span.Range, label, detail, kind string) {
	var k source.CompletionItemKind
	switch kind {
	case "struct":
		k = source.StructCompletionItem
	case "func":
		k = source.FunctionCompletionItem
	case "var":
		k = source.VariableCompletionItem
	case "type":
		k = source.TypeCompletionItem
	case "field":
		k = source.FieldCompletionItem
	case "interface":
		k = source.InterfaceCompletionItem
	case "const":
		k = source.ConstantCompletionItem
	case "method":
		k = source.MethodCompletionItem
	case "package":
		k = source.PackageCompletionItem
	}
	l[spn] = &source.CompletionItem{
		Label:  label,
		Detail: detail,
		Kind:   k,
	}
}

func (l completions) collect(src span.Span, expected []span.Span) {
	l[src] = expected
}

func (l completions) test(t *testing.T, e *packagestest.Exported, items completionItems) {
	if len(l) != expectedCompletionsCount {
		t.Errorf("got %v completions expected %v", len(l), expectedCompletionsCount)
	}
	//TODO: add command line completions tests when it works
}

func (l formats) collect(src span.Span) {
	l[src.URI()] = src
}

func (l formats) test(t *testing.T, e *packagestest.Exported) {
	if len(l) != expectedFormatCount {
		t.Errorf("got %v formats expected %v", len(l), expectedFormatCount)
	}
	//TODO: add command line formatting tests when it works
}

func captureStdOut(t testing.TB, f func()) string {
	r, out, err := os.Pipe()
	if err != nil {
		t.Fatal(err)
	}
	old := os.Stdout
	defer func() {
		os.Stdout = old
		out.Close()
		r.Close()
	}()
	os.Stdout = out
	f()
	out.Close()
	data, err := ioutil.ReadAll(r)
	if err != nil {
		t.Fatal(err)
	}
	return strings.TrimSpace(string(data))
}
