// Copyright 2020 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"
	"go/ast"
	"go/types"
)

// builtinArgKind determines the expected object kind for a builtin
// argument. It attempts to use the AST hints from builtin.go where
// possible.
func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
	builtin, err := c.snapshot.BuiltinFile(ctx)
	if err != nil {
		return 0
	}
	exprIdx := exprAtPos(c.pos, call.Args)

	builtinObj := builtin.File.Scope.Lookup(obj.Name())
	if builtinObj == nil {
		return 0
	}
	decl, ok := builtinObj.Decl.(*ast.FuncDecl)
	if !ok || exprIdx >= len(decl.Type.Params.List) {
		return 0
	}

	switch ptyp := decl.Type.Params.List[exprIdx].Type.(type) {
	case *ast.ChanType:
		return kindChan
	case *ast.ArrayType:
		return kindSlice
	case *ast.MapType:
		return kindMap
	case *ast.Ident:
		switch ptyp.Name {
		case "Type":
			switch obj.Name() {
			case "make":
				return kindChan | kindSlice | kindMap
			case "len":
				return kindSlice | kindMap | kindArray | kindString | kindChan
			case "cap":
				return kindSlice | kindArray | kindChan
			}
		}
	}

	return 0
}

// builtinArgType infers the type of an argument to a builtin
// function. parentInf is the inferred type info for the builtin
// call's parent node.
func (c *completer) builtinArgType(obj types.Object, call *ast.CallExpr, parentInf candidateInference) candidateInference {
	var (
		exprIdx = exprAtPos(c.pos, call.Args)

		// Propagate certain properties from our parent's inference.
		inf = candidateInference{
			typeName:  parentInf.typeName,
			modifiers: parentInf.modifiers,
		}
	)

	switch obj.Name() {
	case "append":
		if exprIdx <= 0 {
			// Infer first append() arg type as apparent return type of
			// append().
			inf.objType = parentInf.objType
			if parentInf.variadic {
				inf.objType = types.NewSlice(inf.objType)
			}
			break
		}

		// For non-initial append() args, infer slice type from the first
		// append() arg, or from parent context.
		if len(call.Args) > 0 {
			inf.objType = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
		}
		if inf.objType == nil {
			inf.objType = parentInf.objType
		}
		if inf.objType == nil {
			break
		}

		inf.objType = deslice(inf.objType)

		// Check if we are completing the variadic append() param.
		inf.variadic = exprIdx == 1 && len(call.Args) <= 2

		// Penalize the first append() argument as a candidate. You
		// don't normally append a slice to itself.
		if sliceChain := objChain(c.pkg.GetTypesInfo(), call.Args[0]); len(sliceChain) > 0 {
			inf.penalized = append(inf.penalized, penalizedObj{objChain: sliceChain, penalty: 0.9})
		}
	case "delete":
		if exprIdx > 0 && len(call.Args) > 0 {
			// Try to fill in expected type of map key.
			firstArgType := c.pkg.GetTypesInfo().TypeOf(call.Args[0])
			if firstArgType != nil {
				if mt, ok := firstArgType.Underlying().(*types.Map); ok {
					inf.objType = mt.Key()
				}
			}
		}
	case "copy":
		var t1, t2 types.Type
		if len(call.Args) > 0 {
			t1 = c.pkg.GetTypesInfo().TypeOf(call.Args[0])
			if len(call.Args) > 1 {
				t2 = c.pkg.GetTypesInfo().TypeOf(call.Args[1])
			}
		}

		// Fill in expected type of either arg if the other is already present.
		if exprIdx == 1 && t1 != nil {
			inf.objType = t1
		} else if exprIdx == 0 && t2 != nil {
			inf.objType = t2
		}
	case "new":
		inf.typeName.wantTypeName = true
		if parentInf.objType != nil {
			// Expected type for "new" is the de-pointered parent type.
			if ptr, ok := parentInf.objType.Underlying().(*types.Pointer); ok {
				inf.objType = ptr.Elem()
			}
		}
	case "make":
		if exprIdx == 0 {
			inf.typeName.wantTypeName = true
			inf.objType = parentInf.objType
		} else {
			inf.objType = types.Typ[types.UntypedInt]
		}
	}

	return inf
}
