// 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 (
	"context"
	"fmt"
	"regexp"
	"strconv"
	"time"

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

// line number (1-based) and message
var errRe = regexp.MustCompile(`template.*:(\d+): (.*)`)

// Diagnostics returns parse errors. There is only one per file.
// The errors are not always helpful. For instance { {end}}
// will likely point to the end of the file.
func Diagnostics(snapshot *cache.Snapshot) map[protocol.DocumentURI][]*cache.Diagnostic {
	diags := make(map[protocol.DocumentURI][]*cache.Diagnostic)
	for uri, fh := range snapshot.Templates() {
		diags[uri] = diagnoseOne(fh)
	}
	return diags
}

func diagnoseOne(fh file.Handle) []*cache.Diagnostic {
	// no need for skipTemplate check, as Diagnose is called on the
	// snapshot's template files
	buf, err := fh.Content()
	if err != nil {
		// TODO: Is a Diagnostic with no Range useful? event.Error also?
		msg := fmt.Sprintf("failed to read %s (%v)", fh.URI().Path(), err)
		return []*cache.Diagnostic{{
			Message:  msg,
			Severity: protocol.SeverityError,
			URI:      fh.URI(),
			Source:   cache.TemplateError,
		}}
	}
	p := parseBuffer(fh.URI(), buf)
	if p.parseErr == nil {
		return nil
	}

	errorf := func(format string, args ...any) []*cache.Diagnostic {
		msg := fmt.Sprintf("malformed template error %q: %s",
			p.parseErr.Error(),
			fmt.Sprintf(format, args...))
		rng, err := p.mapper.OffsetRange(0, 1) // first UTF-16 code
		if err != nil {
			rng = protocol.Range{} // start of file
		}
		return []*cache.Diagnostic{{
			Message:  msg,
			Severity: protocol.SeverityError,
			Range:    rng,
			URI:      fh.URI(),
			Source:   cache.TemplateError,
		}}
	}

	// errors look like `template: :40: unexpected "}" in operand`
	// so the string needs to be parsed
	matches := errRe.FindStringSubmatch(p.parseErr.Error())
	if len(matches) != 3 {
		return errorf("expected 3 matches, got %d (%v)", len(matches), matches)
	}
	lineno, err := strconv.Atoi(matches[1])
	if err != nil {
		return errorf("couldn't convert %q to int, %v", matches[1], err)
	}
	msg := matches[2]

	// Compute the range for the whole (1-based) line.
	rng, err := lineRange(p.mapper, lineno)
	if err != nil {
		return errorf("invalid position: %v", err)
	}

	return []*cache.Diagnostic{{
		Message:  msg,
		Severity: protocol.SeverityError,
		Range:    rng,
		Source:   cache.TemplateError,
	}}
}

// Definition finds the definitions of the symbol at loc. It
// does not understand scoping (if any) in templates. This code is
// for definitions, type definitions, and implementations.
// Results only for variables and templates.
func Definition(snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) ([]protocol.Location, error) {
	x, _, err := symAtRange(fh, rng)
	if err != nil {
		return nil, err
	}
	sym := x.name
	ans := []protocol.Location{}
	// PJW: this is probably a pattern to abstract
	a := parseSet(snapshot.Templates())
	for _, p := range a.files {
		for _, s := range p.symbols {
			if !s.vardef || s.name != sym {
				continue
			}
			loc, err := p.mapper.OffsetLocation(s.offsets())
			if err != nil {
				return nil, err
			}
			ans = append(ans, loc)
		}
	}
	return ans, nil
}

func Hover(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, rng protocol.Range) (*protocol.Hover, error) {
	sym, p, err := symAtRange(fh, rng)
	if err != nil {
		return nil, err
	}

	var value string
	switch sym.kind {
	case protocol.Function:
		value = fmt.Sprintf("function: %s", sym.name)
	case protocol.Variable:
		value = fmt.Sprintf("variable: %s", sym.name)
	case protocol.Constant:
		value = fmt.Sprintf("constant %s", sym.name)
	case protocol.Method: // field or method
		value = fmt.Sprintf("%s: field or method", sym.name)
	case protocol.Package: // template use, template def (PJW: do we want two?)
		value = fmt.Sprintf("template %s\n(add definition)", sym.name)
	case protocol.Namespace:
		value = fmt.Sprintf("template %s defined", sym.name)
	case protocol.Number:
		value = "number"
	case protocol.String:
		value = "string"
	case protocol.Boolean:
		value = "boolean"
	default:
		value = fmt.Sprintf("oops, sym=%#v", sym)
	}

	symRng, err := p.mapper.OffsetRange(sym.offsets())
	if err != nil {
		return nil, err
	}

	return &protocol.Hover{
		Range: symRng,
		Contents: protocol.MarkupContent{
			Kind:  protocol.Markdown,
			Value: value,
		},
	}, nil
}

func References(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, params *protocol.ReferenceParams) ([]protocol.Location, error) {
	sym, _, err := symAtRange(fh, params.Range)
	if err != nil {
		return nil, err
	}
	if sym.name == "" {
		return nil, fmt.Errorf("no symbol at position")
	}
	ans := []protocol.Location{}

	a := parseSet(snapshot.Templates())
	for _, p := range a.files {
		for _, s := range p.symbols {
			if s.name != sym.name {
				continue
			}
			if s.vardef && !params.Context.IncludeDeclaration {
				continue
			}
			loc, err := p.mapper.OffsetLocation(s.offsets())
			if err != nil {
				return nil, err
			}
			ans = append(ans, loc)
		}
	}
	// TODO: do these need to be sorted? (a.files is a map)
	return ans, nil
}

func SemanticTokens(ctx context.Context, snapshot *cache.Snapshot, spn protocol.DocumentURI) (*protocol.SemanticTokens, error) {
	fh, err := snapshot.ReadFile(ctx, spn)
	if err != nil {
		return nil, err
	}
	buf, err := fh.Content()
	if err != nil {
		return nil, err
	}
	p := parseBuffer(fh.URI(), buf)

	var items []semtok.Token
	for _, t := range p.tokens {
		if t.start == t.end {
			continue // vscode doesn't like 0-length tokens
		}
		pos, err := p.mapper.OffsetPosition(t.start)
		if err != nil {
			return nil, err
		}
		// TODO(adonovan): don't ignore the rng restriction, if any.
		items = append(items, semtok.Token{
			Line:  pos.Line,
			Start: pos.Character,
			Len:   uint32(protocol.UTF16Len(p.buf[t.start:t.end])),
			Type:  semtok.TokMacro,
		})
	}
	return &protocol.SemanticTokens{
		Data: semtok.Encode(items, snapshot.Options().EnabledSemanticTokenTypes(), snapshot.Options().EnabledSemanticTokenModifiers()),
		// for small cache, some day. for now, the LSP client ignores this
		// (that is, when the LSP client starts returning these, we can cache)
		ResultID: fmt.Sprintf("%v", time.Now()),
	}, nil
}

// TODO: still need to do rename, etc

func symAtRange(fh file.Handle, rng protocol.Range) (*symbol, *parsed, error) {
	buf, err := fh.Content()
	if err != nil {
		return nil, nil, err
	}
	p := parseBuffer(fh.URI(), buf)
	start, end, err := p.mapper.RangeOffsets(rng)
	if err != nil {
		return nil, nil, err
	}
	var syms []symbol
	for _, s := range p.symbols {
		if s.start <= start && end <= s.start+s.len {
			syms = append(syms, s)
		}
	}
	if len(syms) == 0 {
		return nil, p, fmt.Errorf("no symbol found")
	}
	sym := syms[0]
	return &sym, p, nil
}
