// 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"
	"io/ioutil"
	"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 := ioutil.TempFile(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.View().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 := ioutil.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
}
