// Copyright 2023 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 golang

import (
	"errors"
	"fmt"
	"io/fs"
	"path/filepath"
	"strconv"
	"strings"
	"unicode"
	"unicode/utf8"

	"golang.org/x/tools/gopls/internal/protocol"
)

// ErrNoEmbed is returned by EmbedDefinition when no embed
// directive is found at a particular position.
// As such it indicates that other definitions could be worth checking.
var ErrNoEmbed = errors.New("no embed directive found")

var errStopWalk = errors.New("stop walk")

// EmbedDefinition finds a file matching the embed directive at pos in the mapped file.
// If there is no embed directive at pos, returns ErrNoEmbed.
// If multiple files match the embed pattern, one is picked at random.
func EmbedDefinition(m *protocol.Mapper, pos protocol.Position) ([]protocol.Location, error) {
	pattern, _ := parseEmbedDirective(m, pos)
	if pattern == "" {
		return nil, ErrNoEmbed
	}

	// Find the first matching file.
	var match string
	dir := filepath.Dir(m.URI.Path())
	err := filepath.WalkDir(dir, func(abs string, d fs.DirEntry, e error) error {
		if e != nil {
			return e
		}
		rel, err := filepath.Rel(dir, abs)
		if err != nil {
			return err
		}
		ok, err := filepath.Match(pattern, rel)
		if err != nil {
			return err
		}
		if ok && !d.IsDir() {
			match = abs
			return errStopWalk
		}
		return nil
	})
	if err != nil && !errors.Is(err, errStopWalk) {
		return nil, err
	}
	if match == "" {
		return nil, fmt.Errorf("%q does not match any files in %q", pattern, dir)
	}

	loc := protocol.Location{
		URI: protocol.URIFromPath(match),
		Range: protocol.Range{
			Start: protocol.Position{Line: 0, Character: 0},
		},
	}
	return []protocol.Location{loc}, nil
}

// parseEmbedDirective attempts to parse a go:embed directive argument at pos.
// If successful it return the directive argument and its range, else zero values are returned.
func parseEmbedDirective(m *protocol.Mapper, pos protocol.Position) (string, protocol.Range) {
	lineStart, err := m.PositionOffset(protocol.Position{Line: pos.Line, Character: 0})
	if err != nil {
		return "", protocol.Range{}
	}
	lineEnd, err := m.PositionOffset(protocol.Position{Line: pos.Line + 1, Character: 0})
	if err != nil {
		return "", protocol.Range{}
	}

	text := string(m.Content[lineStart:lineEnd])
	if !strings.HasPrefix(text, "//go:embed") {
		return "", protocol.Range{}
	}
	text = text[len("//go:embed"):]
	offset := lineStart + len("//go:embed")

	// Find the first pattern in text that covers the offset of the pos we are looking for.
	findOffset, err := m.PositionOffset(pos)
	if err != nil {
		return "", protocol.Range{}
	}
	patterns, err := parseGoEmbed(text, offset)
	if err != nil {
		return "", protocol.Range{}
	}
	for _, p := range patterns {
		if p.startOffset <= findOffset && findOffset <= p.endOffset {
			// Found our match.
			rng, err := m.OffsetRange(p.startOffset, p.endOffset)
			if err != nil {
				return "", protocol.Range{}
			}
			return p.pattern, rng
		}
	}

	return "", protocol.Range{}
}

type fileEmbed struct {
	pattern     string
	startOffset int
	endOffset   int
}

// parseGoEmbed patterns that come after the directive.
//
// Copied and adapted from go/build/read.go.
// Replaced token.Position with start/end offset (including quotes if present).
func parseGoEmbed(args string, offset int) ([]fileEmbed, error) {
	trimBytes := func(n int) {
		offset += n
		args = args[n:]
	}
	trimSpace := func() {
		trim := strings.TrimLeftFunc(args, unicode.IsSpace)
		trimBytes(len(args) - len(trim))
	}

	var list []fileEmbed
	for trimSpace(); args != ""; trimSpace() {
		var path string
		pathOffset := offset
	Switch:
		switch args[0] {
		default:
			i := len(args)
			for j, c := range args {
				if unicode.IsSpace(c) {
					i = j
					break
				}
			}
			path = args[:i]
			trimBytes(i)

		case '`':
			var ok bool
			path, _, ok = strings.Cut(args[1:], "`")
			if !ok {
				return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
			}
			trimBytes(1 + len(path) + 1)

		case '"':
			i := 1
			for ; i < len(args); i++ {
				if args[i] == '\\' {
					i++
					continue
				}
				if args[i] == '"' {
					q, err := strconv.Unquote(args[:i+1])
					if err != nil {
						return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args[:i+1])
					}
					path = q
					trimBytes(i + 1)
					break Switch
				}
			}
			if i >= len(args) {
				return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
			}
		}

		if args != "" {
			r, _ := utf8.DecodeRuneInString(args)
			if !unicode.IsSpace(r) {
				return nil, fmt.Errorf("invalid quoted string in //go:embed: %s", args)
			}
		}
		list = append(list, fileEmbed{
			pattern:     path,
			startOffset: pathOffset,
			endOffset:   offset,
		})
	}
	return list, nil
}
