// Copyright 2019 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 cache

import (
	"context"
	"fmt"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/lsp/telemetry"
	"golang.org/x/tools/internal/span"
	"golang.org/x/tools/internal/telemetry/log"
	"golang.org/x/tools/internal/telemetry/tag"
	"golang.org/x/tools/internal/telemetry/trace"
	errors "golang.org/x/xerrors"
)

func (view *view) loadParseTypecheck(ctx context.Context, f *goFile, fh source.FileHandle) error {
	ctx, done := trace.StartSpan(ctx, "cache.view.loadParseTypeCheck", telemetry.URI.Of(f.URI()))
	defer done()

	meta, err := view.load(ctx, f, fh)
	if err != nil {
		return err
	}
	for _, m := range meta {
		imp := &importer{
			view:              view,
			config:            view.Config(ctx),
			seen:              make(map[packageID]struct{}),
			topLevelPackageID: m.id,
		}
		cph, err := imp.checkPackageHandle(ctx, m)
		if err != nil {
			log.Error(ctx, "loadParseTypeCheck: failed to get CheckPackageHandle", err, telemetry.Package.Of(m.id))
			continue
		}
		if _, err := cph.check(ctx); err != nil {
			log.Error(ctx, "loadParseTypeCheck: failed to check package", err, telemetry.Package.Of(m.id))
			continue
		}
		// Cache this package on the file object, since all dependencies are cached in the Import function.
		if err := imp.cachePackage(ctx, cph); err != nil {
			log.Error(ctx, "loadParseTypeCheck: failed to cache package", err, telemetry.Package.Of(m.id))
			continue
		}
	}
	return nil
}

func (view *view) load(ctx context.Context, f *goFile, fh source.FileHandle) ([]*metadata, error) {
	ctx, done := trace.StartSpan(ctx, "cache.view.load", telemetry.URI.Of(f.URI()))
	defer done()

	view.mu.Lock()
	defer view.mu.Unlock()

	view.mcache.mu.Lock()
	defer view.mcache.mu.Unlock()

	var toDelete []packageID
	f.mu.Lock()
	for id, cph := range f.pkgs {
		if cph != nil {
			toDelete = append(toDelete, id)
		}
	}
	f.mu.Unlock()

	// If the AST for this file is trimmed, and we are explicitly type-checking it,
	// don't ignore function bodies.
	if f.wrongParseMode(ctx, fh, source.ParseFull) {
		// Remove the package and all of its reverse dependencies from the cache.
		for _, id := range toDelete {
			f.view.remove(ctx, id, map[packageID]struct{}{})
		}
	}

	// Get the metadata for the file.
	meta, err := view.checkMetadata(ctx, f, fh)
	if err != nil {
		return nil, err
	}
	if len(meta) == 0 {
		return nil, fmt.Errorf("no package metadata found for %s", f.URI())
	}
	return meta, nil
}

// checkMetadata determines if we should run go/packages.Load for this file.
// If yes, update the metadata for the file and its package.
func (v *view) checkMetadata(ctx context.Context, f *goFile, fh source.FileHandle) ([]*metadata, error) {
	// Check if we need to re-run go/packages before loading the package.
	f.mu.Lock()
	runGopackages := v.shouldRunGopackages(ctx, f, fh)
	metadata := f.metadata()
	f.mu.Unlock()

	// The package metadata is correct as-is, so just return it.
	if !runGopackages {
		return metadata, nil
	}

	// Check if the context has been canceled before calling packages.Load.
	if ctx.Err() != nil {
		return nil, ctx.Err()
	}

	ctx, done := trace.StartSpan(ctx, "packages.Load", telemetry.File.Of(f.filename()))
	defer done()
	pkgs, err := packages.Load(v.Config(ctx), fmt.Sprintf("file=%s", f.filename()))
	if len(pkgs) == 0 {
		if err == nil {
			err = errors.Errorf("go/packages.Load: no packages found for %s", f.filename())
		}
		// Return this error as a diagnostic to the user.
		return nil, err
	}
	// Track missing imports as we look at the package's errors.
	missingImports := make(map[packagePath]struct{})

	// Clear metadata since we are re-running go/packages.
	// Reset the file's metadata and type information if we are re-running `go list`.
	f.mu.Lock()
	for k := range f.meta {
		delete(f.meta, k)
	}
	for k := range f.pkgs {
		delete(f.pkgs, k)
	}
	f.mu.Unlock()

	log.Print(ctx, "go/packages.Load", tag.Of("packages", len(pkgs)))
	for _, pkg := range pkgs {
		log.Print(ctx, "go/packages.Load", tag.Of("package", pkg.PkgPath), tag.Of("files", pkg.CompiledGoFiles))
		// Build the import graph for this package.
		if err := v.link(ctx, &importGraph{
			pkgPath:        packagePath(pkg.PkgPath),
			pkg:            pkg,
			parent:         nil,
			missingImports: make(map[packagePath]struct{}),
		}); err != nil {
			return nil, err
		}
	}
	m, err := validateMetadata(ctx, missingImports, f)
	if err != nil {
		return nil, err
	}
	return m, nil
}

func validateMetadata(ctx context.Context, missingImports map[packagePath]struct{}, f *goFile) ([]*metadata, error) {
	f.mu.Lock()
	defer f.mu.Unlock()

	// If `go list` failed to get data for the file in question (this should never happen).
	if len(f.meta) == 0 {
		return nil, errors.Errorf("loadParseTypecheck: no metadata found for %v", f.filename())
	}

	// If we have already seen these missing imports before, and we have type information,
	// there is no need to continue.
	if sameSet(missingImports, f.missingImports) && len(f.pkgs) != 0 {
		return nil, nil
	}

	// Otherwise, update the missing imports map.
	f.missingImports = missingImports

	return f.metadata(), nil
}

func sameSet(x, y map[packagePath]struct{}) bool {
	if len(x) != len(y) {
		return false
	}
	for k := range x {
		if _, ok := y[k]; !ok {
			return false
		}
	}
	return true
}

// shouldRunGopackages reparses a file's package and import declarations to
// determine if they have changed.
// It assumes that the caller holds the lock on the f.mu lock.
func (v *view) shouldRunGopackages(ctx context.Context, f *goFile, fh source.FileHandle) (result bool) {
	if len(f.meta) == 0 || len(f.missingImports) > 0 {
		return true
	}
	// Get file content in case we don't already have it.
	parsed, err := v.session.cache.ParseGoHandle(fh, source.ParseHeader).Parse(ctx)
	if err == context.Canceled {
		log.Error(ctx, "parsing file header", err, tag.Of("file", f.URI()))
		return false
	}
	if parsed == nil {
		return true
	}
	// Check if the package's name has changed, by checking if this is a filename
	// we already know about, and if so, check if its package name has changed.
	for _, m := range f.meta {
		for _, uri := range m.files {
			if span.CompareURI(uri, f.URI()) == 0 {
				if m.name != parsed.Name.Name {
					return true
				}
			}
		}
	}
	// If the package's imports have changed, re-run `go list`.
	if len(f.imports) != len(parsed.Imports) {
		return true
	}
	for i, importSpec := range f.imports {
		if importSpec.Path.Value != parsed.Imports[i].Path.Value {
			return true
		}
	}
	return false
}

type importGraph struct {
	pkgPath        packagePath
	pkg            *packages.Package
	parent         *metadata
	missingImports map[packagePath]struct{}
}

func (v *view) link(ctx context.Context, g *importGraph) error {
	// Recreate the metadata rather than reusing it to avoid locking.
	m := &metadata{
		id:         packageID(g.pkg.ID),
		pkgPath:    g.pkgPath,
		name:       g.pkg.Name,
		typesSizes: g.pkg.TypesSizes,
		errors:     g.pkg.Errors,
	}
	for _, filename := range g.pkg.CompiledGoFiles {
		m.files = append(m.files, span.FileURI(filename))

		// Call the unlocked version of getFile since we are holding the view's mutex.
		f, err := v.getFile(ctx, span.FileURI(filename))
		if err != nil {
			log.Error(ctx, "no file", err, telemetry.File.Of(filename))
			continue
		}
		gof, ok := f.(*goFile)
		if !ok {
			log.Error(ctx, "not a Go file", nil, telemetry.File.Of(filename))
			continue
		}
		// Cache the metadata for this file.
		gof.mu.Lock()
		if gof.meta == nil {
			gof.meta = make(map[packageID]*metadata)
		}
		gof.meta[m.id] = m
		gof.mu.Unlock()
	}

	// Preserve the import graph.
	if original, ok := v.mcache.packages[m.id]; ok {
		m.children = original.children
		m.parents = original.parents
	}
	if m.children == nil {
		m.children = make(map[packageID]*metadata)
	}
	if m.parents == nil {
		m.parents = make(map[packageID]bool)
	}

	// Add the metadata to the cache.
	v.mcache.packages[m.id] = m

	// Connect the import graph.
	if g.parent != nil {
		m.parents[g.parent.id] = true
		g.parent.children[m.id] = m
	}
	for importPath, importPkg := range g.pkg.Imports {
		importPkgPath := packagePath(importPath)
		if importPkgPath == g.pkgPath {
			return fmt.Errorf("cycle detected in %s", importPath)
		}
		// Don't remember any imports with significant errors.
		if importPkgPath != "unsafe" && len(importPkg.CompiledGoFiles) == 0 {
			g.missingImports[importPkgPath] = struct{}{}
			continue
		}
		if _, ok := m.children[packageID(importPkg.ID)]; !ok {
			if err := v.link(ctx, &importGraph{
				pkgPath:        importPkgPath,
				pkg:            importPkg,
				parent:         m,
				missingImports: g.missingImports,
			}); err != nil {
				log.Error(ctx, "error in dependency", err)
			}
		}
	}
	// Clear out any imports that have been removed since the package was last loaded.
	for importID := range m.children {
		child, ok := v.mcache.packages[importID]
		if !ok {
			continue
		}
		importPath := string(child.pkgPath)
		if _, ok := g.pkg.Imports[importPath]; ok {
			continue
		}
		delete(m.children, importID)
		delete(child.parents, m.id)
	}
	return nil
}
