// 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"
	"go/types"
	"strings"
	"time"
)

// MaxDeepCompletions limits deep completion results because in most cases
// there are too many to be useful.
const MaxDeepCompletions = 3

// deepCompletionState stores our state as we search for deep completions.
// "deep completion" refers to searching into objects' fields and methods to
// find more completion candidates.
type deepCompletionState struct {
	// enabled indicates wether deep completion is permitted.
	enabled bool

	// queueClosed is used to disable adding new sub-fields to search queue
	// once we're running out of our time budget.
	queueClosed bool

	// searchQueue holds the current breadth first search queue.
	searchQueue []candidate

	// highScores tracks the highest deep candidate scores we have found
	// so far. This is used to avoid work for low scoring deep candidates.
	highScores [MaxDeepCompletions]float64

	// candidateCount is the count of unique deep candidates encountered
	// so far.
	candidateCount int
}

// enqueue adds a candidate to the search queue.
func (s *deepCompletionState) enqueue(cand candidate) {
	s.searchQueue = append(s.searchQueue, cand)
}

// dequeue removes and returns the leftmost element from the search queue.
func (s *deepCompletionState) dequeue() *candidate {
	var cand *candidate
	cand, s.searchQueue = &s.searchQueue[0], s.searchQueue[1:]
	return cand
}

// scorePenalty computes a deep candidate score penalty. A candidate is
// penalized based on depth to favor shallower candidates. We also give a
// slight bonus to unexported objects and a slight additional penalty to
// function objects.
func (s *deepCompletionState) scorePenalty(cand *candidate) float64 {
	var deepPenalty float64
	for _, dc := range cand.path {
		deepPenalty++

		if !dc.Exported() {
			deepPenalty -= 0.1
		}

		if _, isSig := dc.Type().Underlying().(*types.Signature); isSig {
			deepPenalty += 0.1
		}
	}

	// Normalize penalty to a max depth of 10.
	return deepPenalty / 10
}

// isHighScore returns whether score is among the top MaxDeepCompletions deep
// candidate scores encountered so far. If so, it adds score to highScores,
// possibly displacing an existing high score.
func (s *deepCompletionState) isHighScore(score float64) bool {
	// Invariant: s.highScores is sorted with highest score first. Unclaimed
	// positions are trailing zeros.

	// If we beat an existing score then take its spot.
	for i, deepScore := range s.highScores {
		if score <= deepScore {
			continue
		}

		if deepScore != 0 && i != len(s.highScores)-1 {
			// If this wasn't an empty slot then we need to scooch everyone
			// down one spot.
			copy(s.highScores[i+1:], s.highScores[i:])
		}
		s.highScores[i] = score
		return true
	}

	return false
}

// newPath returns path from search root for an object following a given
// candidate.
func (s *deepCompletionState) newPath(cand *candidate, obj types.Object, invoke bool) ([]types.Object, []string) {
	name := obj.Name()
	if invoke {
		name += "()"
	}

	// copy the slice since we don't want to overwrite the original slice.
	path := append([]types.Object{}, cand.path...)
	names := append([]string{}, cand.names...)

	return append(path, obj), append(names, name)
}

// deepSearch searches a candidate and its subordinate objects for completion
// items if deep completion is enabled and adds the valid candidates to
// completion items.
func (c *completer) deepSearch(ctx context.Context) {
outer:
	for len(c.deepState.searchQueue) > 0 {
		cand := c.deepState.dequeue()
		obj := cand.obj

		// At the top level, dedupe by object.
		if len(cand.path) == 0 {
			if c.seen[cand.obj] {
				continue
			}
			c.seen[cand.obj] = true
		}

		// If obj is not accessible because it lives in another package and is
		// not exported, don't treat it as a completion candidate unless it's
		// a package completion candidate.
		if !c.completionContext.packageCompletion &&
			obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() && !obj.Exported() {
			continue
		}

		// If we want a type name, don't offer non-type name candidates.
		// However, do offer package names since they can contain type names,
		// and do offer any candidate without a type since we aren't sure if it
		// is a type name or not (i.e. unimported candidate).
		if c.wantTypeName() && obj.Type() != nil && !isTypeName(obj) && !isPkgName(obj) {
			continue
		}

		// When searching deep, make sure we don't have a cycle in our chain.
		// We don't dedupe by object because we want to allow both "foo.Baz"
		// and "bar.Baz" even though "Baz" is represented the same types.Object
		// in both.
		for _, seenObj := range cand.path {
			if seenObj == obj {
				continue outer
			}
		}

		c.addCandidate(ctx, cand)

		c.deepState.candidateCount++
		if c.opts.budget > 0 && c.deepState.candidateCount%100 == 0 {
			spent := float64(time.Since(c.startTime)) / float64(c.opts.budget)
			select {
			case <-ctx.Done():
				return
			default:
				// If we are almost out of budgeted time, no further elements
				// should be added to the queue. This ensures remaining time is
				// used for processing current queue.
				if !c.deepState.queueClosed && spent >= 0.85 {
					c.deepState.queueClosed = true
				}
			}
		}

		// if deep search is disabled, don't add any more candidates.
		if !c.deepState.enabled || c.deepState.queueClosed {
			continue
		}

		// Searching members for a type name doesn't make sense.
		if isTypeName(obj) {
			continue
		}
		if obj.Type() == nil {
			continue
		}

		// Don't search embedded fields because they were already included in their
		// parent's fields.
		if v, ok := obj.(*types.Var); ok && v.Embedded() {
			continue
		}

		if sig, ok := obj.Type().Underlying().(*types.Signature); ok {
			// If obj is a function that takes no arguments and returns one
			// value, keep searching across the function call.
			if sig.Params().Len() == 0 && sig.Results().Len() == 1 {
				path, names := c.deepState.newPath(cand, obj, true)
				// The result of a function call is not addressable.
				candidates := c.methodsAndFields(sig.Results().At(0).Type(), false, cand.imp)
				for _, newCand := range candidates {
					newCand.path, newCand.names = path, names
					c.deepState.enqueue(newCand)
				}
			}
		}

		path, names := c.deepState.newPath(cand, obj, false)
		switch obj := obj.(type) {
		case *types.PkgName:
			candidates := c.packageMembers(obj.Imported(), stdScore, cand.imp)
			for _, newCand := range candidates {
				newCand.path, newCand.names = path, names
				c.deepState.enqueue(newCand)
			}
		default:
			candidates := c.methodsAndFields(obj.Type(), cand.addressable, cand.imp)
			for _, newCand := range candidates {
				newCand.path, newCand.names = path, names
				c.deepState.enqueue(newCand)
			}
		}
	}
}

// addCandidate adds a completion candidate to suggestions, without searching
// its members for more candidates.
func (c *completer) addCandidate(ctx context.Context, cand *candidate) {
	obj := cand.obj
	if c.matchingCandidate(cand) {
		cand.score *= highScore

		if p := c.penalty(cand); p > 0 {
			cand.score *= (1 - p)
		}
	} else if isTypeName(obj) {
		// If obj is a *types.TypeName that didn't otherwise match, check
		// if a literal object of this type makes a good candidate.

		// We only care about named types (i.e. don't want builtin types).
		if _, isNamed := obj.Type().(*types.Named); isNamed {
			c.literal(ctx, obj.Type(), cand.imp)
		}
	}

	// Lower score of method calls so we prefer fields and vars over calls.
	if cand.expandFuncCall {
		if sig, ok := obj.Type().Underlying().(*types.Signature); ok && sig.Recv() != nil {
			cand.score *= 0.9
		}
	}

	// Prefer private objects over public ones.
	if !obj.Exported() && obj.Parent() != types.Universe {
		cand.score *= 1.1
	}

	// Favor shallow matches by lowering score according to depth.
	cand.score -= cand.score * c.deepState.scorePenalty(cand)

	if cand.score < 0 {
		cand.score = 0
	}

	cand.name = strings.Join(append(cand.names, cand.obj.Name()), ".")
	if item, err := c.item(ctx, *cand); err == nil {
		c.items = append(c.items, item)
	}
}

// penalty reports a score penalty for cand in the range (0, 1).
// For example, a candidate is penalized if it has already been used
// in another switch case statement.
func (c *completer) penalty(cand *candidate) float64 {
	for _, p := range c.inference.penalized {
		if c.objChainMatches(cand, p.objChain) {
			return p.penalty
		}
	}

	return 0
}

// objChainMatches reports whether cand combined with the surrounding
// object prefix matches chain.
func (c *completer) objChainMatches(cand *candidate, chain []types.Object) bool {
	// For example, when completing:
	//
	//   foo.ba<>
	//
	// If we are considering the deep candidate "bar.baz", cand is baz,
	// objChain is [foo] and deepChain is [bar]. We would match the
	// chain [foo, bar, baz].
	if len(chain) != len(c.inference.objChain)+len(cand.path)+1 {
		return false
	}

	if chain[len(chain)-1] != cand.obj {
		return false
	}

	for i, o := range c.inference.objChain {
		if chain[i] != o {
			return false
		}
	}

	for i, o := range cand.path {
		if chain[i+len(c.inference.objChain)] != o {
			return false
		}
	}

	return true
}
