// Copyright 2020 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 source

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"golang.org/x/tools/gopls/internal/lsp/protocol"
	"golang.org/x/tools/gopls/internal/span"
	"golang.org/x/tools/internal/gocommand"
)

type Annotation string

const (
	// Nil controls nil checks.
	Nil Annotation = "nil"

	// Escape controls diagnostics about escape choices.
	Escape Annotation = "escape"

	// Inline controls diagnostics about inlining choices.
	Inline Annotation = "inline"

	// Bounds controls bounds checking diagnostics.
	Bounds Annotation = "bounds"
)

func GCOptimizationDetails(ctx context.Context, snapshot Snapshot, m *Metadata) (map[span.URI][]*Diagnostic, error) {
	if len(m.CompiledGoFiles) == 0 {
		return nil, nil
	}
	pkgDir := filepath.Dir(m.CompiledGoFiles[0].Filename())
	outDir := filepath.Join(os.TempDir(), fmt.Sprintf("gopls-%d.details", os.Getpid()))

	if err := os.MkdirAll(outDir, 0700); err != nil {
		return nil, err
	}
	tmpFile, err := os.CreateTemp(os.TempDir(), "gopls-x")
	if err != nil {
		return nil, err
	}
	defer os.Remove(tmpFile.Name())

	outDirURI := span.URIFromPath(outDir)
	// GC details doesn't handle Windows URIs in the form of "file:///C:/...",
	// so rewrite them to "file://C:/...". See golang/go#41614.
	if !strings.HasPrefix(outDir, "/") {
		outDirURI = span.URI(strings.Replace(string(outDirURI), "file:///", "file://", 1))
	}
	inv := &gocommand.Invocation{
		Verb: "build",
		Args: []string{
			fmt.Sprintf("-gcflags=-json=0,%s", outDirURI),
			fmt.Sprintf("-o=%s", tmpFile.Name()),
			".",
		},
		WorkingDir: pkgDir,
	}
	_, err = snapshot.RunGoCommandDirect(ctx, Normal, inv)
	if err != nil {
		return nil, err
	}
	files, err := findJSONFiles(outDir)
	if err != nil {
		return nil, err
	}
	reports := make(map[span.URI][]*Diagnostic)
	opts := snapshot.Options()
	var parseError error
	for _, fn := range files {
		uri, diagnostics, err := parseDetailsFile(fn, opts)
		if err != nil {
			// expect errors for all the files, save 1
			parseError = err
		}
		fh := snapshot.FindFile(uri)
		if fh == nil {
			continue
		}
		if pkgDir != filepath.Dir(fh.URI().Filename()) {
			// https://github.com/golang/go/issues/42198
			// sometimes the detail diagnostics generated for files
			// outside the package can never be taken back.
			continue
		}
		reports[fh.URI()] = diagnostics
	}
	return reports, parseError
}

func parseDetailsFile(filename string, options *Options) (span.URI, []*Diagnostic, error) {
	buf, err := os.ReadFile(filename)
	if err != nil {
		return "", nil, err
	}
	var (
		uri         span.URI
		i           int
		diagnostics []*Diagnostic
	)
	type metadata struct {
		File string `json:"file,omitempty"`
	}
	for dec := json.NewDecoder(bytes.NewReader(buf)); dec.More(); {
		// The first element always contains metadata.
		if i == 0 {
			i++
			m := new(metadata)
			if err := dec.Decode(m); err != nil {
				return "", nil, err
			}
			if !strings.HasSuffix(m.File, ".go") {
				continue // <autogenerated>
			}
			uri = span.URIFromPath(m.File)
			continue
		}
		d := new(protocol.Diagnostic)
		if err := dec.Decode(d); err != nil {
			return "", nil, err
		}
		d.Tags = []protocol.DiagnosticTag{} // must be an actual slice
		msg := d.Code.(string)
		if msg != "" {
			msg = fmt.Sprintf("%s(%s)", msg, d.Message)
		}
		if !showDiagnostic(msg, d.Source, options) {
			continue
		}
		var related []protocol.DiagnosticRelatedInformation
		for _, ri := range d.RelatedInformation {
			// TODO(rfindley): The compiler uses LSP-like JSON to encode gc details,
			// however the positions it uses are 1-based UTF-8:
			// https://github.com/golang/go/blob/master/src/cmd/compile/internal/logopt/log_opts.go
			//
			// Here, we adjust for 0-based positions, but do not translate UTF-8 to UTF-16.
			related = append(related, protocol.DiagnosticRelatedInformation{
				Location: protocol.Location{
					URI:   ri.Location.URI,
					Range: zeroIndexedRange(ri.Location.Range),
				},
				Message: ri.Message,
			})
		}
		diagnostic := &Diagnostic{
			URI:      uri,
			Range:    zeroIndexedRange(d.Range),
			Message:  msg,
			Severity: d.Severity,
			Source:   OptimizationDetailsError, // d.Source is always "go compiler" as of 1.16, use our own
			Tags:     d.Tags,
			Related:  related,
		}
		diagnostics = append(diagnostics, diagnostic)
		i++
	}
	return uri, diagnostics, nil
}

// showDiagnostic reports whether a given diagnostic should be shown to the end
// user, given the current options.
func showDiagnostic(msg, source string, o *Options) bool {
	if source != "go compiler" {
		return false
	}
	if o.Annotations == nil {
		return true
	}
	switch {
	case strings.HasPrefix(msg, "canInline") ||
		strings.HasPrefix(msg, "cannotInline") ||
		strings.HasPrefix(msg, "inlineCall"):
		return o.Annotations[Inline]
	case strings.HasPrefix(msg, "escape") || msg == "leak":
		return o.Annotations[Escape]
	case strings.HasPrefix(msg, "nilcheck"):
		return o.Annotations[Nil]
	case strings.HasPrefix(msg, "isInBounds") ||
		strings.HasPrefix(msg, "isSliceInBounds"):
		return o.Annotations[Bounds]
	}
	return false
}

// The range produced by the compiler is 1-indexed, so subtract range by 1.
func zeroIndexedRange(rng protocol.Range) protocol.Range {
	return protocol.Range{
		Start: protocol.Position{
			Line:      rng.Start.Line - 1,
			Character: rng.Start.Character - 1,
		},
		End: protocol.Position{
			Line:      rng.End.Line - 1,
			Character: rng.End.Character - 1,
		},
	}
}

func findJSONFiles(dir string) ([]string, error) {
	ans := []string{}
	f := func(path string, fi os.FileInfo, _ error) error {
		if fi.IsDir() {
			return nil
		}
		if strings.HasSuffix(path, ".json") {
			ans = append(ans, path)
		}
		return nil
	}
	err := filepath.Walk(dir, f)
	return ans, err
}
