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

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

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

// CompilerOptDetails invokes the Go compiler with the "-json=0,dir"
// flag on the packages and tests in the specified directory, parses
// its log of optimization decisions, and returns them as a set of
// diagnostics.
func CompilerOptDetails(ctx context.Context, snapshot *cache.Snapshot, pkgDir protocol.DocumentURI) (map[protocol.DocumentURI][]*cache.Diagnostic, error) {
	outDir, err := os.MkdirTemp("", fmt.Sprintf("gopls-%d.details", os.Getpid()))
	if err != nil {
		return nil, err
	}
	defer func() {
		if err := os.RemoveAll(outDir); err != nil {
			event.Error(ctx, "cleaning details dir", err)
		}
	}()

	outDirURI := protocol.URIFromPath(outDir)
	// 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 = protocol.DocumentURI(strings.Replace(string(outDirURI), "file:///", "file://", 1))
	}

	// We use "go test -c" not "go build" as it covers all three packages
	// (p, "p [p.test]", "p_test [p.test]") in the directory, if they exist.
	// (See also assembly.go.)
	inv, cleanupInvocation, err := snapshot.GoCommandInvocation(cache.NoNetwork, pkgDir.Path(), "test", []string{
		"-c",
		"-vet=off", // weirdly -c doesn't disable vet
		fmt.Sprintf("-gcflags=-json=0,%s", outDirURI), // JSON schema version 0
		fmt.Sprintf("-o=%s", os.DevNull),
		".",
	})
	if err != nil {
		return nil, err
	}
	defer cleanupInvocation()
	_, err = snapshot.View().GoCommandRunner().Run(ctx, *inv)
	if err != nil {
		return nil, err
	}
	files, err := findJSONFiles(outDir)
	if err != nil {
		return nil, err
	}
	reports := make(map[protocol.DocumentURI][]*cache.Diagnostic)
	var parseError error
	for _, fn := range files {
		uri, diagnostics, err := parseDetailsFile(fn, snapshot.Options())
		if err != nil {
			// expect errors for all the files, save 1
			parseError = err
		}
		fh := snapshot.FindFile(uri)
		if fh == nil {
			continue
		}
		if pkgDir != fh.URI().Dir() {
			// Filter compiler diagnostics to the requested directory.
			// 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
}

// parseDetailsFile parses the file written by the Go compiler which contains a JSON-encoded protocol.Diagnostic.
func parseDetailsFile(filename string, options *settings.Options) (protocol.DocumentURI, []*cache.Diagnostic, error) {
	buf, err := os.ReadFile(filename)
	if err != nil {
		return "", nil, err
	}
	var (
		uri         protocol.DocumentURI
		i           int
		diagnostics []*cache.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 = protocol.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
		}

		// zeroIndexedRange subtracts 1 from the line and
		// range, because the compiler output neglects to
		// convert from 1-based UTF-8 coordinates to 0-based UTF-16.
		// (See GOROOT/src/cmd/compile/internal/logopt/log_opts.go.)
		// TODO(rfindley): also translate UTF-8 to UTF-16.
		zeroIndexedRange := func(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,
				},
			}
		}

		var related []protocol.DiagnosticRelatedInformation
		for _, ri := range d.RelatedInformation {
			related = append(related, protocol.DiagnosticRelatedInformation{
				Location: ri.Location.URI.Location(zeroIndexedRange(ri.Location.Range)),
				Message:  ri.Message,
			})
		}
		diagnostic := &cache.Diagnostic{
			URI:      uri,
			Range:    zeroIndexedRange(d.Range),
			Message:  msg,
			Severity: d.Severity,
			Source:   cache.CompilerOptDetailsInfo, // 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 *settings.Options) bool {
	if source != "go compiler" {
		return false
	}
	if o.Annotations == nil {
		return true
	}

	// The strings below were gathered by grepping the source of
	// cmd/compile for literal arguments in calls to logopt.LogOpt.
	// (It is not a well defined set.)
	//
	// - canInlineFunction
	// - cannotInlineCall
	// - cannotInlineFunction
	// - escape
	// - escapes
	// - isInBounds
	// - isSliceInBounds
	// - leak
	// - nilcheck
	//
	// Additional ones not handled by logic below:
	// - copy
	// - iteration-variable-to-{heap,stack}
	// - loop-modified-{range,for}

	switch {
	case strings.HasPrefix(msg, "canInline") ||
		strings.HasPrefix(msg, "cannotInline") ||
		strings.HasPrefix(msg, "inlineCall"):
		return o.Annotations[settings.Inline]
	case strings.HasPrefix(msg, "escape") || msg == "leak":
		return o.Annotations[settings.Escape]
	case strings.HasPrefix(msg, "nilcheck"):
		return o.Annotations[settings.Nil]
	case strings.HasPrefix(msg, "isInBounds") ||
		strings.HasPrefix(msg, "isSliceInBounds"):
		return o.Annotations[settings.Bounds]
	}
	return false
}

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
}
