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

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 {
	// maxDepth limits the deep completion search depth. 0 means
	// disabled and -1 means unlimited.
	maxDepth int

	// chain holds the traversal path as we do a depth-first search through
	// objects' members looking for exact type matches.
	chain []types.Object

	// chainNames holds the names of the chain objects. This allows us to
	// save allocations as we build many deep completion items.
	chainNames []string

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

// push pushes obj onto our search stack. If invoke is true then
// invocation parens "()" will be appended to the object name.
func (s *deepCompletionState) push(obj types.Object, invoke bool) {
	s.chain = append(s.chain, obj)

	name := obj.Name()
	if invoke {
		name += "()"
	}
	s.chainNames = append(s.chainNames, name)
}

// pop pops the last object off our search stack.
func (s *deepCompletionState) pop() {
	s.chain = s.chain[:len(s.chain)-1]
	s.chainNames = s.chainNames[:len(s.chainNames)-1]
}

// chainString joins the chain of objects' names together on ".".
func (s *deepCompletionState) chainString(finalName string) string {
	s.chainNames = append(s.chainNames, finalName)
	chainStr := strings.Join(s.chainNames, ".")
	s.chainNames = s.chainNames[:len(s.chainNames)-1]
	return chainStr
}

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

// 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() float64 {
	var deepPenalty float64
	for _, dc := range s.chain {
		deepPenalty += 1

		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
}

func (c *completer) inDeepCompletion() bool {
	return len(c.deepState.chain) > 0
}

// shouldPrune returns whether we should prune the current deep
// candidate search to reduce the overall search scope. The
// maximum search depth is reduced gradually as we use up our
// completionBudget.
func (c *completer) shouldPrune() bool {
	if !c.inDeepCompletion() {
		return false
	}

	// Check our remaining budget every 100 candidates.
	if c.opts.budget > 0 && c.deepState.candidateCount%100 == 0 {
		spent := float64(time.Since(c.startTime)) / float64(c.opts.budget)

		switch {
		case spent >= 0.90:
			// We are close to exhausting our budget. Disable deep completions.
			c.deepState.maxDepth = 0
		case spent >= 0.75:
			// We are running out of budget, reduce max depth again.
			c.deepState.maxDepth = 2
		case spent >= 0.5:
			// We have used half our budget, reduce max depth again.
			c.deepState.maxDepth = 3
		case spent >= 0.25:
			// We have used a good chunk of our budget, so start limiting our search.
			// By default the search depth is unlimited, so this limit, while still
			// generous, is normally a huge reduction in search scope that will result
			// in our search completing very soon.
			c.deepState.maxDepth = 4
		}
	}

	c.deepState.candidateCount++

	if c.deepState.maxDepth >= 0 {
		return len(c.deepState.chain) >= c.deepState.maxDepth
	}

	return false
}

// deepSearch searches through cand's subordinate objects for more
// completion items.
func (c *completer) deepSearch(ctx context.Context, cand candidate) {
	if c.deepState.maxDepth == 0 {
		return
	}

	obj := cand.obj

	// If we are definitely completing a struct field name, deep completions
	// don't make sense.
	if c.wantStructFieldCompletions() && c.enclosingCompositeLiteral.inKey {
		return
	}

	// Don't search into type names.
	if isTypeName(obj) {
		return
	}

	if obj.Type() == nil {
		return
	}

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

	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 {
			// Pass invoke=true since the function needs to be invoked in
			// the deep chain.
			c.deepState.push(obj, true)
			// The result of a function call is not addressable.
			c.methodsAndFields(ctx, sig.Results().At(0).Type(), false, cand.imp)
			c.deepState.pop()
		}
	}

	// Push this object onto our search stack.
	c.deepState.push(obj, false)

	switch obj := obj.(type) {
	case *types.PkgName:
		c.packageMembers(ctx, obj.Imported(), stdScore, cand.imp)
	default:
		c.methodsAndFields(ctx, obj.Type(), cand.addressable, cand.imp)
	}

	// Pop the object off our search stack.
	c.deepState.pop()
}
