// 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 completion

import (
	"context"
	"errors"
	"fmt"
	"go/ast"
	"go/doc"
	"go/types"
	"strings"

	"golang.org/x/tools/gopls/internal/golang"
	"golang.org/x/tools/gopls/internal/golang/completion/snippet"
	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/safetoken"
	"golang.org/x/tools/gopls/internal/util/typesutil"
	internalastutil "golang.org/x/tools/internal/astutil"
	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/imports"
)

var (
	errNoMatch  = errors.New("not a surrounding match")
	errLowScore = errors.New("not a high scoring candidate")
)

// item formats a candidate to a CompletionItem.
func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, error) {
	obj := cand.obj

	// if the object isn't a valid match against the surrounding, return early.
	matchScore := c.matcher.Score(cand.name)
	if matchScore <= 0 {
		return CompletionItem{}, errNoMatch
	}
	cand.score *= float64(matchScore)

	// Ignore deep candidates that won't be in the MaxDeepCompletions anyway.
	if len(cand.path) != 0 && !c.deepState.isHighScore(cand.score) {
		return CompletionItem{}, errLowScore
	}

	// Handle builtin types separately.
	if obj.Parent() == types.Universe {
		return c.formatBuiltin(ctx, cand)
	}

	var (
		label         = cand.name
		detail        = types.TypeString(obj.Type(), c.qual)
		insert        = label
		kind          = protocol.TextCompletion
		snip          snippet.Builder
		protocolEdits []protocol.TextEdit
	)
	if obj.Type() == nil {
		detail = ""
	}

	type hasTypeParams interface{ TypeParams() *types.TypeParamList }
	if genericType, _ := obj.Type().(hasTypeParams); genericType != nil && isTypeName(obj) && c.wantTypeParams() {
		// golang/go#71044: note that type names can be basic types, even in
		// receiver position, for invalid code.
		tparams := genericType.TypeParams()
		label += typesutil.FormatTypeParams(tparams)
		insert = label // maintain invariant above (label == insert)
	}

	snip.WriteText(insert)

	switch obj := obj.(type) {
	case *types.TypeName:
		detail, kind = golang.FormatType(obj.Type(), c.qual)
	case *types.Const:
		kind = protocol.ConstantCompletion
	case *types.Var:
		if _, ok := obj.Type().(*types.Struct); ok {
			detail = "struct{...}" // for anonymous unaliased struct types
		} else if obj.IsField() {
			var err error
			detail, err = golang.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qual, c.mq)
			if err != nil {
				return CompletionItem{}, err
			}
		}
		if obj.IsField() {
			kind = protocol.FieldCompletion
			c.structFieldSnippet(cand, detail, &snip)
		} else {
			kind = protocol.VariableCompletion
		}
		if obj.Type() == nil {
			break
		}
	case *types.Func:
		if obj.Signature().Recv() == nil {
			kind = protocol.FunctionCompletion
		} else {
			kind = protocol.MethodCompletion
		}
	case *types.PkgName:
		kind = protocol.ModuleCompletion
		detail = fmt.Sprintf("%q", obj.Imported().Path())
	case *types.Label:
		kind = protocol.ConstantCompletion
		detail = "label"
	}

	var prefix string
	for _, mod := range cand.mods {
		switch mod {
		case reference:
			prefix = "&" + prefix
		case dereference:
			prefix = "*" + prefix
		case chanRead:
			prefix = "<-" + prefix
		}
	}

	var (
		suffix   string
		funcType = obj.Type()
	)
Suffixes:
	for _, mod := range cand.mods {
		switch mod {
		case invoke:
			if sig, ok := funcType.Underlying().(*types.Signature); ok {
				s, err := golang.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qual, c.mq)
				if err != nil {
					return CompletionItem{}, err
				}

				tparams := s.TypeParams()
				if len(tparams) > 0 {
					// Eliminate the suffix of type parameters that are
					// likely redundant because they can probably be
					// inferred from the argument types (#51783).
					//
					// We don't bother doing the reverse inference from
					// result types as result-only type parameters are
					// quite unusual.
					free := inferableTypeParams(sig)
					for i := sig.TypeParams().Len() - 1; i >= 0; i-- {
						tparam := sig.TypeParams().At(i)
						if !free[tparam] {
							break
						}
						tparams = tparams[:i] // eliminate
					}
				}

				c.functionCallSnippet("", tparams, s.Params(), &snip)
				if sig.Results().Len() == 1 {
					funcType = sig.Results().At(0).Type()
				}
				detail = "func" + s.Format()
			}

			if !c.opts.snippets {
				// Without snippets the candidate will not include "()". Don't
				// add further suffixes since they will be invalid. For
				// example, with snippets "foo()..." would become "foo..."
				// without snippets if we added the dotDotDot.
				break Suffixes
			}
		case takeSlice:
			suffix += "[:]"
		case takeDotDotDot:
			suffix += "..."
		case index:
			snip.WriteText("[")
			snip.WritePlaceholder(nil)
			snip.WriteText("]")
		}
	}

	// If this candidate needs an additional import statement,
	// add the additional text edits needed.
	if cand.imp != nil {
		addlEdits, err := c.importEdits(cand.imp)

		if err != nil {
			return CompletionItem{}, err
		}

		protocolEdits = append(protocolEdits, addlEdits...)
		if kind != protocol.ModuleCompletion {
			if detail != "" {
				detail += " "
			}
			detail += fmt.Sprintf("(from %q)", cand.imp.importPath)
		}
	}

	if cand.convertTo != nil {
		conv := c.formatConversion(cand.convertTo)
		prefix = conv.prefix + prefix
		suffix = conv.suffix
	}

	if prefix != "" {
		// If we are in a selector, add an edit to place prefix before selector.
		if sel := enclosingSelector(c.path, c.pos); sel != nil {
			edits, err := c.editText(sel.Pos(), sel.Pos(), prefix)
			if err != nil {
				return CompletionItem{}, err
			}
			protocolEdits = append(protocolEdits, edits...)
		} else {
			// If there is no selector, just stick the prefix at the start.
			insert = prefix + insert
			snip.PrependText(prefix)
		}
	}

	if suffix != "" {
		insert += suffix
		snip.WriteText(suffix)
	}

	detail = strings.TrimPrefix(detail, "untyped ")
	// override computed detail with provided detail, if something is provided.
	if cand.detail != "" {
		detail = cand.detail
	}
	item := CompletionItem{
		Label:               label,
		InsertText:          insert,
		AdditionalTextEdits: protocolEdits,
		Detail:              detail,
		Kind:                kind,
		Score:               cand.score,
		Depth:               len(cand.path),
		snippet:             &snip,
		isSlice:             isSlice(obj),
	}
	// If the user doesn't want documentation for completion items.
	if !c.opts.documentation {
		return item, nil
	}
	pos := safetoken.StartPosition(c.pkg.FileSet(), obj.Pos())

	// We ignore errors here, because some types, like "unsafe" or "error",
	// may not have valid positions that we can use to get documentation.
	if !pos.IsValid() {
		return item, nil
	}

	comment, err := golang.HoverDocForObject(ctx, c.snapshot, c.pkg.FileSet(), obj)
	if err != nil {
		event.Error(ctx, fmt.Sprintf("failed to find Hover for %q", obj.Name()), err)
		return item, nil
	}
	if c.opts.fullDocumentation {
		item.Documentation = comment.Text()
	} else {
		item.Documentation = doc.Synopsis(comment.Text())
	}
	if internalastutil.Deprecation(comment) != "" {
		if c.snapshot.Options().CompletionTags {
			item.Tags = []protocol.CompletionItemTag{protocol.ComplDeprecated}
		} else if c.snapshot.Options().CompletionDeprecated {
			item.Deprecated = true
		}
	}

	return item, nil
}

// conversionEdits represents the string edits needed to make a type conversion
// of an expression.
type conversionEdits struct {
	prefix, suffix string
}

// formatConversion returns the edits needed to make a type conversion
// expression, including parentheses if necessary.
//
// Returns empty conversionEdits if convertTo is nil.
func (c *completer) formatConversion(convertTo types.Type) conversionEdits {
	if convertTo == nil {
		return conversionEdits{}
	}

	typeName := types.TypeString(convertTo, c.qual)
	switch t := convertTo.(type) {
	// We need extra parens when casting to these types. For example,
	// we need "(*int)(foo)", not "*int(foo)".
	case *types.Pointer, *types.Signature:
		typeName = "(" + typeName + ")"
	case *types.Basic:
		// If the types are incompatible (as determined by typeMatches), then we
		// must need a conversion here. However, if the target type is untyped,
		// don't suggest converting to e.g. "untyped float" (golang/go#62141).
		if t.Info()&types.IsUntyped != 0 {
			typeName = types.TypeString(types.Default(convertTo), c.qual)
		}
	}
	return conversionEdits{prefix: typeName + "(", suffix: ")"}
}

// importEdits produces the text edits necessary to add the given import to the current file.
func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
	if imp == nil {
		return nil, nil
	}

	pgf, err := c.pkg.File(protocol.URIFromPath(c.filename))
	if err != nil {
		return nil, err
	}

	return golang.ComputeImportFixEdits(c.snapshot.Options().Local, pgf.Src, &imports.ImportFix{
		StmtInfo: imports.ImportInfo{
			ImportPath: imp.importPath,
			Name:       imp.name,
		},
		// IdentName is unused on this path and is difficult to get.
		FixType: imports.AddImport,
	})
}

func (c *completer) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) {
	obj := cand.obj
	item := CompletionItem{
		Label:      obj.Name(),
		InsertText: obj.Name(),
		Score:      cand.score,
	}
	switch obj.(type) {
	case *types.Const:
		item.Kind = protocol.ConstantCompletion
	case *types.Builtin:
		item.Kind = protocol.FunctionCompletion
		sig, err := golang.NewBuiltinSignature(ctx, c.snapshot, obj.Name())
		if err != nil {
			return CompletionItem{}, err
		}
		item.Detail = "func" + sig.Format()
		item.snippet = &snippet.Builder{}
		// The signature inferred for a built-in is instantiated, so TypeParams=∅.
		c.functionCallSnippet(obj.Name(), sig.TypeParams(), sig.Params(), item.snippet)
	case *types.TypeName:
		if types.IsInterface(obj.Type()) {
			item.Kind = protocol.InterfaceCompletion
		} else {
			item.Kind = protocol.ClassCompletion
		}
	case *types.Nil:
		item.Kind = protocol.VariableCompletion
	}
	return item, nil
}

// decide if the type params (if any) should be part of the completion
// which only possible for types.Named and types.Signature
// (so far, only in receivers, e.g.; func (s *GENERIC[K, V])..., which is a types.Named)
func (c *completer) wantTypeParams() bool {
	// Need to be lexically in a receiver, and a child of an IndexListExpr
	// (but IndexListExpr only exists with go1.18)
	start := c.path[0].Pos()
	for i, nd := range c.path {
		if fd, ok := nd.(*ast.FuncDecl); ok {
			if i > 0 && fd.Recv != nil && start < fd.Recv.End() {
				return true
			} else {
				return false
			}
		}
	}
	return false
}

// inferableTypeParams returns the set of type parameters
// of sig that are constrained by (inferred from) the argument types.
func inferableTypeParams(sig *types.Signature) map[*types.TypeParam]bool {
	free := make(map[*types.TypeParam]bool)

	// visit adds to free all the free type parameters of t.
	var visit func(t types.Type)
	visit = func(t types.Type) {
		switch t := t.(type) {
		case *types.Array:
			visit(t.Elem())
		case *types.Chan:
			visit(t.Elem())
		case *types.Map:
			visit(t.Key())
			visit(t.Elem())
		case *types.Pointer:
			visit(t.Elem())
		case *types.Slice:
			visit(t.Elem())
		case *types.Interface:
			for i := range t.NumExplicitMethods() {
				visit(t.ExplicitMethod(i).Type())
			}
			for i := range t.NumEmbeddeds() {
				visit(t.EmbeddedType(i))
			}
		case *types.Union:
			for i := range t.Len() {
				visit(t.Term(i).Type())
			}
		case *types.Signature:
			if tp := t.TypeParams(); tp != nil {
				// Generic signatures only appear as the type of generic
				// function declarations, so this isn't really reachable.
				for i := range tp.Len() {
					visit(tp.At(i).Constraint())
				}
			}
			visit(t.Params())
			visit(t.Results())
		case *types.Tuple:
			for i := range t.Len() {
				visit(t.At(i).Type())
			}
		case *types.Struct:
			for i := range t.NumFields() {
				visit(t.Field(i).Type())
			}
		case *types.TypeParam:
			free[t] = true
		case *types.Alias:
			visit(types.Unalias(t))
		case *types.Named:
			targs := t.TypeArgs()
			for i := range targs.Len() {
				visit(targs.At(i))
			}
		case *types.Basic:
			// nop
		default:
			panic(t)
		}
	}

	visit(sig.Params())

	// Perform induction through constraints.
restart:
	for i := range sig.TypeParams().Len() {
		tp := sig.TypeParams().At(i)
		if free[tp] {
			n := len(free)
			visit(tp.Constraint())
			if len(free) > n {
				goto restart // iterate until fixed point
			}
		}
	}
	return free
}
