// 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"
	"go/types"

	"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"
)

type metadata struct {
	id          packageID
	pkgPath     packagePath
	name        string
	files       []span.URI
	typesSizes  types.Sizes
	errors      []packages.Error
	deps        []packageID
	missingDeps map[packagePath]struct{}

	// config is the *packages.Config associated with the loaded package.
	config *packages.Config
}

func (s *snapshot) load(ctx context.Context, uri span.URI) ([]*metadata, error) {
	ctx, done := trace.StartSpan(ctx, "cache.view.load", telemetry.URI.Of(uri))
	defer done()

	cfg := s.view.Config(ctx)
	pkgs, err := packages.Load(cfg, fmt.Sprintf("file=%s", uri.Filename()))

	// If the context was canceled, return early.
	// Otherwise, we might be type-checking an incomplete result.
	if err == context.Canceled {
		return nil, errors.Errorf("no metadata for %s: %v", uri.Filename(), err)
	}
	log.Print(ctx, "go/packages.Load", tag.Of("packages", len(pkgs)))
	if len(pkgs) == 0 {
		if err == nil {
			err = errors.Errorf("go/packages.Load: no packages found for %s", uri)
		}
		// Return this error as a diagnostic to the user.
		return nil, err
	}
	m, prevMissingImports, err := s.updateMetadata(ctx, uri, pkgs, cfg)
	if err != nil {
		return nil, err
	}
	meta, err := validateMetadata(ctx, m, prevMissingImports)
	if err != nil {
		return nil, err
	}
	return meta, nil
}

func validateMetadata(ctx context.Context, metadata []*metadata, prevMissingImports map[packageID]map[packagePath]struct{}) ([]*metadata, error) {
	// If we saw incorrect metadata for this package previously, don't both rechecking it.
	for _, m := range metadata {
		if len(m.missingDeps) > 0 {
			prev, ok := prevMissingImports[m.id]
			// There are missing imports that we previously hadn't seen before.
			if !ok {
				return metadata, nil
			}
			// The set of missing imports has changed.
			if !sameSet(prev, m.missingDeps) {
				return metadata, nil
			}
		} else {
			// There are no missing imports.
			return metadata, nil
		}
	}
	return nil, 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
}

// shouldLoad reparses a file's package and import declarations to
// determine if they have changed.
func (c *cache) shouldLoad(ctx context.Context, s *snapshot, originalFH, currentFH source.FileHandle) bool {
	if originalFH == nil {
		return true
	}

	// Get the original and current parsed files in order to check package name and imports.
	original, _, _, originalErr := c.ParseGoHandle(originalFH, source.ParseHeader).Parse(ctx)
	current, _, _, currentErr := c.ParseGoHandle(currentFH, source.ParseHeader).Parse(ctx)
	if originalErr != nil || currentErr != nil {
		return (originalErr == nil) != (currentErr == nil)
	}

	// Check if the package's metadata has changed. The cases handled are:
	//
	//    1. A package's name has changed
	//    2. A file's imports have changed
	//
	if original.Name.Name != current.Name.Name {
		return true
	}
	// If the package's imports have changed, re-run `go list`.
	if len(original.Imports) != len(current.Imports) {
		return true
	}
	for i, importSpec := range original.Imports {
		// TODO: Handle the case where the imports have just been re-ordered.
		if importSpec.Path.Value != current.Imports[i].Path.Value {
			return true
		}
	}
	return false
}

func (s *snapshot) updateMetadata(ctx context.Context, uri span.URI, pkgs []*packages.Package, cfg *packages.Config) ([]*metadata, map[packageID]map[packagePath]struct{}, error) {
	// Clear metadata since we are re-running go/packages.
	prevMissingImports := make(map[packageID]map[packagePath]struct{})
	m := s.getMetadataForURI(uri)

	for _, m := range m {
		if len(m.missingDeps) > 0 {
			prevMissingImports[m.id] = m.missingDeps
		}
	}

	var results []*metadata
	for _, pkg := range pkgs {
		log.Print(ctx, "go/packages.Load", tag.Of("package", pkg.PkgPath), tag.Of("files", pkg.CompiledGoFiles))

		// Set the metadata for this package.
		if err := s.updateImports(ctx, packagePath(pkg.PkgPath), pkg, cfg, map[packageID]struct{}{}); err != nil {
			return nil, nil, err
		}
		m := s.getMetadata(packageID(pkg.ID))
		if m != nil {
			results = append(results, m)
		}
	}

	// Rebuild the import graph when the metadata is updated.
	s.clearAndRebuildImportGraph()

	if len(results) == 0 {
		return nil, nil, errors.Errorf("no metadata for %s", uri)
	}
	return results, prevMissingImports, nil
}

func (s *snapshot) updateImports(ctx context.Context, pkgPath packagePath, pkg *packages.Package, cfg *packages.Config, seen map[packageID]struct{}) error {
	id := packageID(pkg.ID)
	if _, ok := seen[id]; ok {
		return errors.Errorf("import cycle detected: %q", id)
	}
	// Recreate the metadata rather than reusing it to avoid locking.
	m := &metadata{
		id:         id,
		pkgPath:    pkgPath,
		name:       pkg.Name,
		typesSizes: pkg.TypesSizes,
		errors:     pkg.Errors,
		config:     cfg,
	}
	seen[id] = struct{}{}
	for _, filename := range pkg.CompiledGoFiles {
		uri := span.FileURI(filename)
		m.files = append(m.files, uri)

		s.addID(uri, m.id)
	}

	copied := make(map[packageID]struct{})
	for k, v := range seen {
		copied[k] = v
	}
	for importPath, importPkg := range pkg.Imports {
		importPkgPath := packagePath(importPath)
		importID := packageID(importPkg.ID)

		m.deps = append(m.deps, importID)

		// Don't remember any imports with significant errors.
		if importPkgPath != "unsafe" && len(importPkg.CompiledGoFiles) == 0 {
			if m.missingDeps == nil {
				m.missingDeps = make(map[packagePath]struct{})
			}
			m.missingDeps[importPkgPath] = struct{}{}
			continue
		}
		dep := s.getMetadata(importID)
		if dep == nil {
			if err := s.updateImports(ctx, importPkgPath, importPkg, cfg, copied); err != nil {
				log.Error(ctx, "error in dependency", err)
			}
		}
	}

	// Add the metadata to the cache.
	s.setMetadata(m)

	return nil
}
