// Copyright 2021 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 template

import (
	"bytes"
	"context"
	"fmt"
	"go/scanner"
	"go/token"
	"strings"

	"golang.org/x/tools/gopls/internal/file"
	"golang.org/x/tools/gopls/internal/lsp/cache"
	"golang.org/x/tools/gopls/internal/lsp/protocol"
)

// information needed for completion
type completer struct {
	p      *Parsed
	pos    protocol.Position
	offset int // offset of the start of the Token
	ctx    protocol.CompletionContext
	syms   map[string]symbol
}

func Completion(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pos protocol.Position, context protocol.CompletionContext) (*protocol.CompletionList, error) {
	all := New(snapshot.Templates())
	var start int // the beginning of the Token (completed or not)
	syms := make(map[string]symbol)
	var p *Parsed
	for fn, fc := range all.files {
		// collect symbols from all template files
		filterSyms(syms, fc.symbols)
		if fn.Path() != fh.URI().Path() {
			continue
		}
		if start = inTemplate(fc, pos); start == -1 {
			return nil, nil
		}
		p = fc
	}
	if p == nil {
		// this cannot happen unless the search missed a template file
		return nil, fmt.Errorf("%s not found", fh.Identity().URI.Path())
	}
	c := completer{
		p:      p,
		pos:    pos,
		offset: start + len(Left),
		ctx:    context,
		syms:   syms,
	}
	return c.complete()
}

func filterSyms(syms map[string]symbol, ns []symbol) {
	for _, xsym := range ns {
		switch xsym.kind {
		case protocol.Method, protocol.Package, protocol.Boolean, protocol.Namespace,
			protocol.Function:
			syms[xsym.name] = xsym // we don't care which symbol we get
		case protocol.Variable:
			if xsym.name != "dot" {
				syms[xsym.name] = xsym
			}
		case protocol.Constant:
			if xsym.name == "nil" {
				syms[xsym.name] = xsym
			}
		}
	}
}

// return the starting position of the enclosing token, or -1 if none
func inTemplate(fc *Parsed, pos protocol.Position) int {
	// pos is the pos-th character. if the cursor is at the beginning
	// of the file, pos is 0. That is, we've only seen characters before pos
	// 1. pos might be in a Token, return tk.Start
	// 2. pos might be after an elided but before a Token, return elided
	// 3. return -1 for false
	offset := fc.FromPosition(pos)
	// this could be a binary search, as the tokens are ordered
	for _, tk := range fc.tokens {
		if tk.Start < offset && offset <= tk.End {
			return tk.Start
		}
	}
	for _, x := range fc.elided {
		if x > offset {
			// fc.elided is sorted
			break
		}
		// If the interval [x,offset] does not contain Left or Right
		// then provide completions. (do we need the test for Right?)
		if !bytes.Contains(fc.buf[x:offset], Left) && !bytes.Contains(fc.buf[x:offset], Right) {
			return x
		}
	}
	return -1
}

var (
	keywords = []string{"if", "with", "else", "block", "range", "template", "end}}", "end"}
	globals  = []string{"and", "call", "html", "index", "slice", "js", "len", "not", "or",
		"urlquery", "printf", "println", "print", "eq", "ne", "le", "lt", "ge", "gt"}
)

// find the completions. start is the offset of either the Token enclosing pos, or where
// the incomplete token starts.
// The error return is always nil.
func (c *completer) complete() (*protocol.CompletionList, error) {
	ans := &protocol.CompletionList{IsIncomplete: true, Items: []protocol.CompletionItem{}}
	start := c.p.FromPosition(c.pos)
	sofar := c.p.buf[c.offset:start]
	if len(sofar) == 0 || sofar[len(sofar)-1] == ' ' || sofar[len(sofar)-1] == '\t' {
		return ans, nil
	}
	// sofar could be parsed by either c.analyzer() or scan(). The latter is precise
	// and slower, but fast enough
	words := scan(sofar)
	// 1. if pattern starts $, show variables
	// 2. if pattern starts ., show methods (and . by itself?)
	// 3. if len(words) == 1, show firstWords (but if it were a |, show functions and globals)
	// 4. ...? (parenthetical expressions, arguments, ...) (packages, namespaces, nil?)
	if len(words) == 0 {
		return nil, nil // if this happens, why were we called?
	}
	pattern := words[len(words)-1]
	if pattern[0] == '$' {
		// should we also return a raw "$"?
		for _, s := range c.syms {
			if s.kind == protocol.Variable && weakMatch(s.name, pattern) > 0 {
				ans.Items = append(ans.Items, protocol.CompletionItem{
					Label:  s.name,
					Kind:   protocol.VariableCompletion,
					Detail: "Variable",
				})
			}
		}
		return ans, nil
	}
	if pattern[0] == '.' {
		for _, s := range c.syms {
			if s.kind == protocol.Method && weakMatch("."+s.name, pattern) > 0 {
				ans.Items = append(ans.Items, protocol.CompletionItem{
					Label:  s.name,
					Kind:   protocol.MethodCompletion,
					Detail: "Method/member",
				})
			}
		}
		return ans, nil
	}
	// could we get completion attempts in strings or numbers, and if so, do we care?
	// globals
	for _, kw := range globals {
		if weakMatch(kw, pattern) != 0 {
			ans.Items = append(ans.Items, protocol.CompletionItem{
				Label:  kw,
				Kind:   protocol.KeywordCompletion,
				Detail: "Function",
			})
		}
	}
	// and functions
	for _, s := range c.syms {
		if s.kind == protocol.Function && weakMatch(s.name, pattern) != 0 {
			ans.Items = append(ans.Items, protocol.CompletionItem{
				Label:  s.name,
				Kind:   protocol.FunctionCompletion,
				Detail: "Function",
			})
		}
	}
	// keywords if we're at the beginning
	if len(words) <= 1 || len(words[len(words)-2]) == 1 && words[len(words)-2][0] == '|' {
		for _, kw := range keywords {
			if weakMatch(kw, pattern) != 0 {
				ans.Items = append(ans.Items, protocol.CompletionItem{
					Label:  kw,
					Kind:   protocol.KeywordCompletion,
					Detail: "keyword",
				})
			}
		}
	}
	return ans, nil
}

// version of c.analyze that uses go/scanner.
func scan(buf []byte) []string {
	fset := token.NewFileSet()
	fp := fset.AddFile("", -1, len(buf))
	var sc scanner.Scanner
	sc.Init(fp, buf, func(pos token.Position, msg string) {}, scanner.ScanComments)
	ans := make([]string, 0, 10) // preallocating gives a measurable savings
	for {
		_, tok, lit := sc.Scan() // tok is an int
		if tok == token.EOF {
			break // done
		} else if tok == token.SEMICOLON && lit == "\n" {
			continue // don't care, but probably can't happen
		} else if tok == token.PERIOD {
			ans = append(ans, ".") // lit is empty
		} else if tok == token.IDENT && len(ans) > 0 && ans[len(ans)-1] == "." {
			ans[len(ans)-1] = "." + lit
		} else if tok == token.IDENT && len(ans) > 0 && ans[len(ans)-1] == "$" {
			ans[len(ans)-1] = "$" + lit
		} else if lit != "" {
			ans = append(ans, lit)
		}
	}
	return ans
}

// pattern is what the user has typed
func weakMatch(choice, pattern string) float64 {
	lower := strings.ToLower(choice)
	// for now, use only lower-case everywhere
	pattern = strings.ToLower(pattern)
	// The first char has to match
	if pattern[0] != lower[0] {
		return 0
	}
	// If they start with ., then the second char has to match
	from := 1
	if pattern[0] == '.' {
		if len(pattern) < 2 {
			return 1 // pattern just a ., so it matches
		}
		if pattern[1] != lower[1] {
			return 0
		}
		from = 2
	}
	// check that all the characters of pattern occur as a subsequence of choice
	i, j := from, from
	for ; i < len(lower) && j < len(pattern); j++ {
		if pattern[j] == lower[i] {
			i++
			if i >= len(lower) {
				return 0
			}
		}
	}
	if j < len(pattern) {
		return 0
	}
	return 1
}
