// 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 types.Type
}

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

type Field struct {
	Name    string
	Doc     string
	JSONTag string
	Type    types.Type
	// 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 {
		c.Result = sig.Results().At(0).Type()
	}
	ftype := node.Type.(*ast.FuncType)
	if sig.Params().Len() != ftype.Params.NumFields() {
		panic("bug: mismatching method params")
	}
	for i, p := range ftype.Params.List {
		pt := sig.Params().At(i)
		fld, err := l.loadField(pkg, p, pt, "")
		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, node *ast.Field, obj *types.Var, tag string) (*Field, error) {
	if existing, ok := l.loaded[obj]; ok {
		return existing, nil
	}
	fld := &Field{
		Name:    obj.Name(),
		Doc:     strings.TrimSpace(node.Doc.Text()),
		Type:    obj.Type(),
		JSONTag: reflect.StructTag(tag).Get("json"),
	}
	under := fld.Type.Underlying()
	if p, ok := under.(*types.Pointer); ok {
		under = p.Elem()
	}
	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())
				}
			}
			node2, err := findField(pkg2, obj2.Pos())
			if err != nil {
				return nil, err
			}
			tag := s.Tag(i)
			structField, err := l.loadField(pkg2, node2, obj2, 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
}
