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

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.View().BuiltinPackage(ctx)
	if err != nil {
		return 0
	}
	exprIdx := exprAtPos(c.pos, call.Args)

	decl, ok := builtin.Package().Scope.Lookup(obj.Name()).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)
		inf     = candidateInference{}
	)

	switch obj.Name() {
	case "append":
		if parentInf.objType == nil {
			break
		}
		inf.objType = parentInf.objType

		// Check if we are completing the variadic append() param.
		if exprIdx == 1 && len(call.Args) <= 2 {
			inf.variadicType = deslice(inf.objType)
		} else if exprIdx > 0 {
			// If we are completing an individual element of the variadic
			// param, "deslice" the expected type.
			inf.objType = deslice(inf.objType)
		}
	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.Int]
		}
	}

	return inf
}
