// 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 := m.URI.DirPath()
	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
}
