// Copyright 2018 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 (
	"context"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/internal/event"
	"golang.org/x/tools/internal/lsp/debug/tag"
	"golang.org/x/tools/internal/lsp/protocol"
	"golang.org/x/tools/internal/span"
)

type Diagnostic struct {
	Range    protocol.Range
	Message  string
	Source   string
	Severity protocol.DiagnosticSeverity
	Tags     []protocol.DiagnosticTag

	Related []RelatedInformation
}

type SuggestedFix struct {
	Title   string
	Edits   map[span.URI][]protocol.TextEdit
	Command *protocol.Command
}

type RelatedInformation struct {
	URI     span.URI
	Range   protocol.Range
	Message string
}

func GetTypeCheckDiagnostics(ctx context.Context, snapshot Snapshot, pkg Package) TypeCheckDiagnostics {
	onlyIgnoredFiles := true
	for _, pgf := range pkg.CompiledGoFiles() {
		onlyIgnoredFiles = onlyIgnoredFiles && snapshot.IgnoredFile(pgf.URI)
	}
	if onlyIgnoredFiles {
		return TypeCheckDiagnostics{}
	}

	// Prepare any additional reports for the errors in this package.
	for _, e := range pkg.GetErrors() {
		// We only need to handle lower-level errors.
		if e.Kind != ListError {
			continue
		}
		// If no file is associated with the error, pick an open file from the package.
		if e.URI.Filename() == "" {
			for _, pgf := range pkg.CompiledGoFiles() {
				if snapshot.IsOpen(pgf.URI) {
					e.URI = pgf.URI
				}
			}
		}
	}
	return typeCheckDiagnostics(ctx, snapshot, pkg)
}

func Analyze(ctx context.Context, snapshot Snapshot, pkg Package, typeCheckResult TypeCheckDiagnostics) (map[span.URI][]*Diagnostic, error) {
	// Exit early if the context has been canceled. This also protects us
	// from a race on Options, see golang/go#36699.
	if ctx.Err() != nil {
		return nil, ctx.Err()
	}
	// If we don't have any list or parse errors, run analyses.
	analyzers := pickAnalyzers(snapshot, typeCheckResult.HasTypeErrors)
	analysisErrors, err := snapshot.Analyze(ctx, pkg.ID(), analyzers...)
	if err != nil {
		return nil, err
	}

	reports := emptyDiagnostics(pkg)
	// Report diagnostics and errors from root analyzers.
	for _, e := range analysisErrors {
		// If the diagnostic comes from a "convenience" analyzer, it is not
		// meant to provide diagnostics, but rather only suggested fixes.
		// Skip these types of errors in diagnostics; we will use their
		// suggested fixes when providing code actions.
		if isConvenienceAnalyzer(e.Category) {
			continue
		}
		// This is a bit of a hack, but clients > 3.15 will be able to grey out unnecessary code.
		// If we are deleting code as part of all of our suggested fixes, assume that this is dead code.
		// TODO(golang/go#34508): Return these codes from the diagnostics themselves.
		var tags []protocol.DiagnosticTag
		if onlyDeletions(e.SuggestedFixes) {
			tags = append(tags, protocol.Unnecessary)
		}
		// Type error analyzers only alter the tags for existing type errors.
		if _, ok := snapshot.View().Options().TypeErrorAnalyzers[e.Category]; ok {
			existingDiagnostics := typeCheckResult.Diagnostics[e.URI]
			for _, d := range existingDiagnostics {
				if r := protocol.CompareRange(e.Range, d.Range); r != 0 {
					continue
				}
				if e.Message != d.Message {
					continue
				}
				d.Tags = append(d.Tags, tags...)
			}
		} else {
			reports[e.URI] = append(reports[e.URI], &Diagnostic{
				Range:    e.Range,
				Message:  e.Message,
				Source:   e.Category,
				Severity: protocol.SeverityWarning,
				Tags:     tags,
				Related:  e.Related,
			})
		}
	}
	return reports, nil
}

func pickAnalyzers(snapshot Snapshot, hadTypeErrors bool) []*analysis.Analyzer {
	// Always run convenience analyzers.
	categories := []map[string]Analyzer{snapshot.View().Options().ConvenienceAnalyzers}
	// If we had type errors, only run type error analyzers.
	if hadTypeErrors {
		categories = append(categories, snapshot.View().Options().TypeErrorAnalyzers)
	} else {
		categories = append(categories, snapshot.View().Options().DefaultAnalyzers, snapshot.View().Options().StaticcheckAnalyzers)
	}
	var analyzers []*analysis.Analyzer
	for _, m := range categories {
		for _, a := range m {
			if a.IsEnabled(snapshot.View()) {
				analyzers = append(analyzers, a.Analyzer)
			}
		}
	}
	return analyzers
}

func FileDiagnostics(ctx context.Context, snapshot Snapshot, uri span.URI) (VersionedFileIdentity, []*Diagnostic, error) {
	fh, err := snapshot.GetVersionedFile(ctx, uri)
	if err != nil {
		return VersionedFileIdentity{}, nil, err
	}
	pkg, _, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
	if err != nil {
		return VersionedFileIdentity{}, nil, err
	}
	typeCheckResults := GetTypeCheckDiagnostics(ctx, snapshot, pkg)
	diagnostics := typeCheckResults.Diagnostics[fh.URI()]
	if !typeCheckResults.HasParseOrListErrors {
		reports, err := Analyze(ctx, snapshot, pkg, typeCheckResults)
		if err != nil {
			return VersionedFileIdentity{}, nil, err
		}
		diagnostics = append(diagnostics, reports[fh.URI()]...)
	}
	return fh.VersionedFileIdentity(), diagnostics, nil
}

type TypeCheckDiagnostics struct {
	HasTypeErrors        bool
	HasParseOrListErrors bool
	Diagnostics          map[span.URI][]*Diagnostic
}

type diagnosticSet struct {
	listErrors, parseErrors, typeErrors []*Diagnostic
}

func typeCheckDiagnostics(ctx context.Context, snapshot Snapshot, pkg Package) TypeCheckDiagnostics {
	ctx, done := event.Start(ctx, "source.diagnostics", tag.Package.Of(pkg.ID()))
	_ = ctx // circumvent SA4006
	defer done()

	diagSets := make(map[span.URI]*diagnosticSet)
	for _, e := range pkg.GetErrors() {
		diag := &Diagnostic{
			Message:  e.Message,
			Range:    e.Range,
			Severity: protocol.SeverityError,
			Related:  e.Related,
		}
		set, ok := diagSets[e.URI]
		if !ok {
			set = &diagnosticSet{}
			diagSets[e.URI] = set
		}
		switch e.Kind {
		case ParseError:
			set.parseErrors = append(set.parseErrors, diag)
			diag.Source = "syntax"
		case TypeError:
			set.typeErrors = append(set.typeErrors, diag)
			diag.Source = "compiler"
		case ListError:
			set.listErrors = append(set.listErrors, diag)
			diag.Source = "go list"
		}
	}
	typecheck := TypeCheckDiagnostics{
		Diagnostics: emptyDiagnostics(pkg),
	}
	for uri, set := range diagSets {
		// Don't report type errors if there are parse errors or list errors.
		diags := set.typeErrors
		switch {
		case len(set.parseErrors) > 0:
			typecheck.HasParseOrListErrors = true
			diags = set.parseErrors
		case len(set.listErrors) > 0:
			typecheck.HasParseOrListErrors = true
			if len(pkg.MissingDependencies()) > 0 {
				diags = set.listErrors
			}
		case len(set.typeErrors) > 0:
			typecheck.HasTypeErrors = true
		}
		typecheck.Diagnostics[uri] = diags
	}
	return typecheck
}

func emptyDiagnostics(pkg Package) map[span.URI][]*Diagnostic {
	diags := map[span.URI][]*Diagnostic{}
	for _, pgf := range pkg.CompiledGoFiles() {
		if _, ok := diags[pgf.URI]; !ok {
			diags[pgf.URI] = nil
		}
	}
	return diags
}

// onlyDeletions returns true if all of the suggested fixes are deletions.
func onlyDeletions(fixes []SuggestedFix) bool {
	for _, fix := range fixes {
		for _, edits := range fix.Edits {
			for _, edit := range edits {
				if edit.NewText != "" {
					return false
				}
				if protocol.ComparePosition(edit.Range.Start, edit.Range.End) == 0 {
					return false
				}
			}
		}
	}
	return len(fixes) > 0
}

func isConvenienceAnalyzer(category string) bool {
	for _, a := range DefaultOptions().ConvenienceAnalyzers {
		if category == a.Analyzer.Name {
			return true
		}
	}
	return false
}
