// 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"
	"text/template/parse"
	"unicode/utf8"

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

// in local coordinates, to be translated to protocol.DocumentSymbol
type symbol struct {
	start  int // for sorting
	length int // in runes (unicode code points)
	name   string
	kind   protocol.SymbolKind
	vardef bool // is this a variable definition?
	// do we care about selection range, or children?
	// no children yet, and selection range is the same as range
}

func (s symbol) String() string {
	return fmt.Sprintf("{%d,%d,%s,%s,%v}", s.start, s.length, s.name, s.kind, s.vardef)
}

// for FieldNode or VariableNode (or ChainNode?)
func (p *Parsed) fields(flds []string, x parse.Node) []symbol {
	ans := []symbol{}
	// guessing that there are no embedded blanks allowed. The doc is unclear
	lookfor := ""
	switch x.(type) {
	case *parse.FieldNode:
		for _, f := range flds {
			lookfor += "." + f // quadratic, but probably ok
		}
	case *parse.VariableNode:
		lookfor = flds[0]
		for i := 1; i < len(flds); i++ {
			lookfor += "." + flds[i]
		}
	case *parse.ChainNode: // PJW, what are these?
		for _, f := range flds {
			lookfor += "." + f // quadratic, but probably ok
		}
	default:
		// If these happen they will happen even if gopls is restarted
		// and the users does the same thing, so it is better not to panic.
		// context.Background() is used because we don't have access
		// to any other context. [we could, but it would be complicated]
		event.Log(context.Background(), fmt.Sprintf("%T unexpected in fields()", x))
		return nil
	}
	if len(lookfor) == 0 {
		event.Log(context.Background(), fmt.Sprintf("no strings in fields() %#v", x))
		return nil
	}
	startsAt := int(x.Position())
	ix := bytes.Index(p.buf[startsAt:], []byte(lookfor)) // HasPrefix? PJW?
	if ix < 0 || ix > len(lookfor) {                     // lookfor expected to be at start (or so)
		// probably golang.go/#43388, so back up
		startsAt -= len(flds[0]) + 1
		ix = bytes.Index(p.buf[startsAt:], []byte(lookfor)) // ix might be 1? PJW
		if ix < 0 {
			return ans
		}
	}
	at := ix + startsAt
	for _, f := range flds {
		at += 1 // .
		kind := protocol.Method
		if f[0] == '$' {
			kind = protocol.Variable
		}
		sym := symbol{name: f, kind: kind, start: at, length: utf8.RuneCount([]byte(f))}
		if kind == protocol.Variable && len(p.stack) > 1 {
			if pipe, ok := p.stack[len(p.stack)-2].(*parse.PipeNode); ok {
				for _, y := range pipe.Decl {
					if x == y {
						sym.vardef = true
					}
				}
			}
		}
		ans = append(ans, sym)
		at += len(f)
	}
	return ans
}

func (p *Parsed) findSymbols() {
	if len(p.stack) == 0 {
		return
	}
	n := p.stack[len(p.stack)-1]
	pop := func() {
		p.stack = p.stack[:len(p.stack)-1]
	}
	if n == nil { // allowing nil simplifies the code
		pop()
		return
	}
	nxt := func(nd parse.Node) {
		p.stack = append(p.stack, nd)
		p.findSymbols()
	}
	switch x := n.(type) {
	case *parse.ActionNode:
		nxt(x.Pipe)
	case *parse.BoolNode:
		// need to compute the length from the value
		msg := fmt.Sprintf("%v", x.True)
		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: len(msg), kind: protocol.Boolean})
	case *parse.BranchNode:
		nxt(x.Pipe)
		nxt(x.List)
		nxt(x.ElseList)
	case *parse.ChainNode:
		p.symbols = append(p.symbols, p.fields(x.Field, x)...)
		nxt(x.Node)
	case *parse.CommandNode:
		for _, a := range x.Args {
			nxt(a)
		}
	//case *parse.CommentNode: // go 1.16
	//	log.Printf("implement %d", x.Type())
	case *parse.DotNode:
		sym := symbol{name: "dot", kind: protocol.Variable, start: int(x.Pos), length: 1}
		p.symbols = append(p.symbols, sym)
	case *parse.FieldNode:
		p.symbols = append(p.symbols, p.fields(x.Ident, x)...)
	case *parse.IdentifierNode:
		sym := symbol{name: x.Ident, kind: protocol.Function, start: int(x.Pos),
			length: utf8.RuneCount([]byte(x.Ident))}
		p.symbols = append(p.symbols, sym)
	case *parse.IfNode:
		nxt(&x.BranchNode)
	case *parse.ListNode:
		if x != nil { // wretched typed nils. Node should have an IfNil
			for _, nd := range x.Nodes {
				nxt(nd)
			}
		}
	case *parse.NilNode:
		sym := symbol{name: "nil", kind: protocol.Constant, start: int(x.Pos), length: 3}
		p.symbols = append(p.symbols, sym)
	case *parse.NumberNode:
		// no name; ascii
		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: len(x.Text), kind: protocol.Number})
	case *parse.PipeNode:
		if x == nil { // {{template "foo"}}
			return
		}
		for _, d := range x.Decl {
			nxt(d)
		}
		for _, c := range x.Cmds {
			nxt(c)
		}
	case *parse.RangeNode:
		nxt(&x.BranchNode)
	case *parse.StringNode:
		// no name
		sz := utf8.RuneCount([]byte(x.Text))
		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: sz, kind: protocol.String})
	case *parse.TemplateNode: // invoking a template
		// x.Pos points to the quote before the name
		p.symbols = append(p.symbols, symbol{name: x.Name, kind: protocol.Package, start: int(x.Pos) + 1,
			length: utf8.RuneCount([]byte(x.Name))})
		nxt(x.Pipe)
	case *parse.TextNode:
		if len(x.Text) == 1 && x.Text[0] == '\n' {
			break
		}
		// nothing to report, but build one for hover
		sz := utf8.RuneCount(x.Text)
		p.symbols = append(p.symbols, symbol{start: int(x.Pos), length: sz, kind: protocol.Constant})
	case *parse.VariableNode:
		p.symbols = append(p.symbols, p.fields(x.Ident, x)...)
	case *parse.WithNode:
		nxt(&x.BranchNode)

	}
	pop()
}

// DocumentSymbols returns a hierarchy of the symbols defined in a template file.
// (The hierarchy is flat. SymbolInformation might be better.)
func DocumentSymbols(snapshot *cache.Snapshot, fh file.Handle) ([]protocol.DocumentSymbol, error) {
	buf, err := fh.Content()
	if err != nil {
		return nil, err
	}
	p := parseBuffer(buf)
	if p.ParseErr != nil {
		return nil, p.ParseErr
	}
	var ans []protocol.DocumentSymbol
	for _, s := range p.symbols {
		if s.kind == protocol.Constant {
			continue
		}
		d := kindStr(s.kind)
		if d == "Namespace" {
			d = "Template"
		}
		if s.vardef {
			d += "(def)"
		} else {
			d += "(use)"
		}
		r := p.Range(s.start, s.length)
		y := protocol.DocumentSymbol{
			Name:           s.name,
			Detail:         d,
			Kind:           s.kind,
			Range:          r,
			SelectionRange: r, // or should this be the entire {{...}}?
		}
		ans = append(ans, y)
	}
	return ans, nil
}
