// 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 (
	"go/ast"

	"golang.org/x/tools/gopls/internal/protocol"
	"golang.org/x/tools/gopls/internal/util/astutil"
)

const (
	BREAK       = "break"
	CASE        = "case"
	CHAN        = "chan"
	CONST       = "const"
	CONTINUE    = "continue"
	DEFAULT     = "default"
	DEFER       = "defer"
	ELSE        = "else"
	FALLTHROUGH = "fallthrough"
	FOR         = "for"
	FUNC        = "func"
	GO          = "go"
	GOTO        = "goto"
	IF          = "if"
	IMPORT      = "import"
	INTERFACE   = "interface"
	MAP         = "map"
	PACKAGE     = "package"
	RANGE       = "range"
	RETURN      = "return"
	SELECT      = "select"
	STRUCT      = "struct"
	SWITCH      = "switch"
	TYPE        = "type"
	VAR         = "var"
)

// addKeywordCompletions offers keyword candidates appropriate at the position.
func (c *completer) addKeywordCompletions() {
	seen := make(map[string]bool)

	if c.wantTypeName() && c.inference.objType == nil {
		// If we want a type name but don't have an expected obj type,
		// include "interface", "struct", "func", "chan", and "map".

		// "interface" and "struct" are more common declaring named types.
		// Give them a higher score if we are in a type declaration.
		structIntf, funcChanMap := stdScore, highScore
		if len(c.path) > 1 {
			if _, namedDecl := c.path[1].(*ast.TypeSpec); namedDecl {
				structIntf, funcChanMap = highScore, stdScore
			}
		}

		c.addKeywordItems(seen, structIntf, STRUCT, INTERFACE)
		c.addKeywordItems(seen, funcChanMap, FUNC, CHAN, MAP)
	}

	// If we are at the file scope, only offer decl keywords. We don't
	// get *ast.Idents at the file scope because non-keyword identifiers
	// turn into *ast.BadDecl, not *ast.Ident.
	if len(c.path) == 1 || is[*ast.File](c.path[1]) {
		c.addKeywordItems(seen, stdScore, TYPE, CONST, VAR, FUNC, IMPORT)
		return
	} else if _, ok := c.path[0].(*ast.Ident); !ok {
		// Otherwise only offer keywords if the client is completing an identifier.
		return
	}

	if len(c.path) > 2 {
		// Offer "range" if we are in ast.ForStmt.Init. This is what the
		// AST looks like before "range" is typed, e.g. "for i := r<>".
		if loop, ok := c.path[2].(*ast.ForStmt); ok && loop.Init != nil && astutil.NodeContains(loop.Init, c.pos) {
			c.addKeywordItems(seen, stdScore, RANGE)
		}
	}

	// Only suggest keywords if we are beginning a statement.
	switch n := c.path[1].(type) {
	case *ast.BlockStmt, *ast.ExprStmt:
		// OK - our ident must be at beginning of statement.
	case *ast.CommClause:
		// Make sure we aren't in the Comm statement.
		if !n.Colon.IsValid() || c.pos <= n.Colon {
			return
		}
	case *ast.CaseClause:
		// Make sure we aren't in the case List.
		if !n.Colon.IsValid() || c.pos <= n.Colon {
			return
		}
	default:
		return
	}

	// Filter out keywords depending on scope
	// Skip the first one because we want to look at the enclosing scopes
	path := c.path[1:]
	for i, n := range path {
		switch node := n.(type) {
		case *ast.CaseClause:
			// only recommend "fallthrough" and "break" within the bodies of a case clause
			if c.pos > node.Colon {
				c.addKeywordItems(seen, stdScore, BREAK)
				// "fallthrough" is only valid in switch statements.
				// A case clause is always nested within a block statement in a switch statement,
				// that block statement is nested within either a TypeSwitchStmt or a SwitchStmt.
				if i+2 >= len(path) {
					continue
				}
				if _, ok := path[i+2].(*ast.SwitchStmt); ok {
					c.addKeywordItems(seen, stdScore, FALLTHROUGH)
				}
			}
		case *ast.CommClause:
			if c.pos > node.Colon {
				c.addKeywordItems(seen, stdScore, BREAK)
			}
		case *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.SwitchStmt:
			c.addKeywordItems(seen, stdScore, CASE, DEFAULT)
		case *ast.ForStmt, *ast.RangeStmt:
			c.addKeywordItems(seen, stdScore, BREAK, CONTINUE)
		// This is a bit weak, functions allow for many keywords
		case *ast.FuncDecl:
			if node.Body != nil && c.pos > node.Body.Lbrace {
				c.addKeywordItems(seen, stdScore, DEFER, RETURN, FOR, GO, SWITCH, SELECT, IF, ELSE, VAR, CONST, GOTO, TYPE)
			}
		}
	}
}

// addKeywordItems dedupes and adds completion items for the specified
// keywords with the specified score.
func (c *completer) addKeywordItems(seen map[string]bool, score float64, kws ...string) {
	for _, kw := range kws {
		if seen[kw] {
			continue
		}
		seen[kw] = true

		if matchScore := c.matcher.Score(kw); matchScore > 0 {
			c.items = append(c.items, CompletionItem{
				Label:      kw,
				Kind:       protocol.KeywordCompletion,
				InsertText: kw,
				Score:      score * float64(matchScore),
			})
		}
	}
}
