// Copyright 2021 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 commandmeta provides metadata about LSP commands, by analyzing the
// command.Interface type.
package commandmeta

import (
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
	"reflect"
	"strings"
	"unicode"

	"golang.org/x/tools/go/ast/astutil"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/command"
)

type Command struct {
	MethodName string
	Name       string
	// TODO(rFindley): I think Title can actually be eliminated. In all cases
	// where we use it, there is probably a more appropriate contextual title.
	Title  string
	Doc    string
	Args   []*Field
	Result *Field
}

func (c *Command) ID() string {
	return command.ID(c.Name)
}

type Field struct {
	Name     string
	Doc      string
	JSONTag  string
	Type     types.Type
	FieldMod string
	// In some circumstances, we may want to recursively load additional field
	// descriptors for fields of struct types, documenting their internals.
	Fields []*Field
}

func Load() (*packages.Package, []*Command, error) {
	pkgs, err := packages.Load(
		&packages.Config{
			Mode:       packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,
			BuildFlags: []string{"-tags=generate"},
		},
		"golang.org/x/tools/internal/lsp/command",
	)
	if err != nil {
		return nil, nil, fmt.Errorf("packages.Load: %v", err)
	}
	pkg := pkgs[0]
	if len(pkg.Errors) > 0 {
		return pkg, nil, pkg.Errors[0]
	}

	// For a bit of type safety, use reflection to get the interface name within
	// the package scope.
	it := reflect.TypeOf((*command.Interface)(nil)).Elem()
	obj := pkg.Types.Scope().Lookup(it.Name()).Type().Underlying().(*types.Interface)

	// Load command metadata corresponding to each interface method.
	var commands []*Command
	loader := fieldLoader{make(map[types.Object]*Field)}
	for i := 0; i < obj.NumMethods(); i++ {
		m := obj.Method(i)
		c, err := loader.loadMethod(pkg, m)
		if err != nil {
			return nil, nil, fmt.Errorf("loading %s: %v", m.Name(), err)
		}
		commands = append(commands, c)
	}
	return pkg, commands, nil
}

// fieldLoader loads field information, memoizing results to prevent infinite
// recursion.
type fieldLoader struct {
	loaded map[types.Object]*Field
}

var universeError = types.Universe.Lookup("error").Type()

func (l *fieldLoader) loadMethod(pkg *packages.Package, m *types.Func) (*Command, error) {
	node, err := findField(pkg, m.Pos())
	if err != nil {
		return nil, err
	}
	title, doc := splitDoc(node.Doc.Text())
	c := &Command{
		MethodName: m.Name(),
		Name:       lspName(m.Name()),
		Doc:        doc,
		Title:      title,
	}
	sig := m.Type().Underlying().(*types.Signature)
	rlen := sig.Results().Len()
	if rlen > 2 || rlen == 0 {
		return nil, fmt.Errorf("must have 1 or 2 returns, got %d", rlen)
	}
	finalResult := sig.Results().At(rlen - 1)
	if !types.Identical(finalResult.Type(), universeError) {
		return nil, fmt.Errorf("final return must be error")
	}
	if rlen == 2 {
		obj := sig.Results().At(0)
		c.Result, err = l.loadField(pkg, obj, "", "")
		if err != nil {
			return nil, err
		}
	}
	for i := 0; i < sig.Params().Len(); i++ {
		obj := sig.Params().At(i)
		fld, err := l.loadField(pkg, obj, "", "")
		if err != nil {
			return nil, err
		}
		if i == 0 {
			// Lazy check that the first argument is a context. We could relax this,
			// but then the generated code gets more complicated.
			if named, ok := fld.Type.(*types.Named); !ok || named.Obj().Name() != "Context" || named.Obj().Pkg().Path() != "context" {
				return nil, fmt.Errorf("first method parameter must be context.Context")
			}
			// Skip the context argument, as it is implied.
			continue
		}
		c.Args = append(c.Args, fld)
	}
	return c, nil
}

func (l *fieldLoader) loadField(pkg *packages.Package, obj *types.Var, doc, tag string) (*Field, error) {
	if existing, ok := l.loaded[obj]; ok {
		return existing, nil
	}
	fld := &Field{
		Name:    obj.Name(),
		Doc:     strings.TrimSpace(doc),
		Type:    obj.Type(),
		JSONTag: reflect.StructTag(tag).Get("json"),
	}
	under := fld.Type.Underlying()
	// Quick-and-dirty handling for various underyling types.
	switch p := under.(type) {
	case *types.Pointer:
		under = p.Elem().Underlying()
	case *types.Array:
		under = p.Elem().Underlying()
		fld.FieldMod = fmt.Sprintf("[%d]", p.Len())
	case *types.Slice:
		under = p.Elem().Underlying()
		fld.FieldMod = "[]"
	}

	if s, ok := under.(*types.Struct); ok {
		for i := 0; i < s.NumFields(); i++ {
			obj2 := s.Field(i)
			pkg2 := pkg
			if obj2.Pkg() != pkg2.Types {
				pkg2, ok = pkg.Imports[obj2.Pkg().Path()]
				if !ok {
					return nil, fmt.Errorf("missing import for %q: %q", pkg.ID, obj2.Pkg().Path())
				}
			}
			node, err := findField(pkg2, obj2.Pos())
			if err != nil {
				return nil, err
			}
			tag := s.Tag(i)
			structField, err := l.loadField(pkg2, obj2, node.Doc.Text(), tag)
			if err != nil {
				return nil, err
			}
			fld.Fields = append(fld.Fields, structField)
		}
	}
	return fld, nil
}

// splitDoc parses a command doc string to separate the title from normal
// documentation.
//
// The doc comment should be of the form: "MethodName: Title\nDocumentation"
func splitDoc(text string) (title, doc string) {
	docParts := strings.SplitN(text, "\n", 2)
	titleParts := strings.SplitN(docParts[0], ":", 2)
	if len(titleParts) > 1 {
		title = strings.TrimSpace(titleParts[1])
	}
	if len(docParts) > 1 {
		doc = strings.TrimSpace(docParts[1])
	}
	return title, doc
}

// lspName returns the normalized command name to use in the LSP.
func lspName(methodName string) string {
	words := splitCamel(methodName)
	for i := range words {
		words[i] = strings.ToLower(words[i])
	}
	return strings.Join(words, "_")
}

// splitCamel splits s into words, according to camel-case word boundaries.
// Initialisms are grouped as a single word.
//
// For example:
//  "RunTests" -> []string{"Run", "Tests"}
//  "GCDetails" -> []string{"GC", "Details"}
func splitCamel(s string) []string {
	var words []string
	for len(s) > 0 {
		last := strings.LastIndexFunc(s, unicode.IsUpper)
		if last < 0 {
			last = 0
		}
		if last == len(s)-1 {
			// Group initialisms as a single word.
			last = 1 + strings.LastIndexFunc(s[:last], func(r rune) bool { return !unicode.IsUpper(r) })
		}
		words = append(words, s[last:])
		s = s[:last]
	}
	for i := 0; i < len(words)/2; i++ {
		j := len(words) - i - 1
		words[i], words[j] = words[j], words[i]
	}
	return words
}

// findField finds the struct field or interface method positioned at pos,
// within the AST.
func findField(pkg *packages.Package, pos token.Pos) (*ast.Field, error) {
	fset := pkg.Fset
	var file *ast.File
	for _, f := range pkg.Syntax {
		if fset.Position(f.Pos()).Filename == fset.Position(pos).Filename {
			file = f
			break
		}
	}
	if file == nil {
		return nil, fmt.Errorf("no file for pos %v", pos)
	}
	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
	// This is fragile, but in the cases we care about, the field will be in
	// path[1].
	return path[1].(*ast.Field), nil
}
