// 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/ast"
	"go/scanner"
	"go/token"
	"go/types"
	"sync"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/span"
)

type importer struct {
	view *view

	// seen maintains the set of previously imported packages.
	// If we have seen a package that is already in this map, we have a circular import.
	seen map[packageID]struct{}

	// topLevelPkgID is the ID of the package from which type-checking began.
	topLevelPkgID packageID

	ctx  context.Context
	fset *token.FileSet
}

func (imp *importer) Import(pkgPath string) (*types.Package, error) {
	id, ok := imp.view.mcache.ids[packagePath(pkgPath)]
	if !ok {
		return nil, fmt.Errorf("no known ID for %s", pkgPath)
	}
	pkg, err := imp.getPkg(id)
	if err != nil {
		return nil, err
	}
	return pkg.types, nil
}

func (imp *importer) getPkg(id packageID) (*pkg, error) {
	if _, ok := imp.seen[id]; ok {
		return nil, fmt.Errorf("circular import detected")
	}
	imp.view.pcache.mu.Lock()
	e, ok := imp.view.pcache.packages[id]

	if ok {
		// cache hit
		imp.view.pcache.mu.Unlock()
		// wait for entry to become ready
		<-e.ready
	} else {
		// cache miss
		e = &entry{ready: make(chan struct{})}
		imp.view.pcache.packages[id] = e
		imp.view.pcache.mu.Unlock()

		// This goroutine becomes responsible for populating
		// the entry and broadcasting its readiness.
		e.pkg, e.err = imp.typeCheck(id)
		close(e.ready)
	}

	if e.err != nil {
		// If the import had been previously canceled, and that error cached, try again.
		if e.err == context.Canceled && imp.ctx.Err() == nil {
			imp.view.pcache.mu.Lock()
			// Clear out canceled cache entry if it is still there.
			if imp.view.pcache.packages[id] == e {
				delete(imp.view.pcache.packages, id)
			}
			imp.view.pcache.mu.Unlock()
			return imp.getPkg(id)
		}
		return nil, e.err
	}

	return e.pkg, nil
}

func (imp *importer) typeCheck(id packageID) (*pkg, error) {
	meta, ok := imp.view.mcache.packages[id]
	if !ok {
		return nil, fmt.Errorf("no metadata for %v", id)
	}
	pkg := &pkg{
		id:         meta.id,
		pkgPath:    meta.pkgPath,
		imports:    make(map[packagePath]*pkg),
		typesSizes: meta.typesSizes,
		typesInfo: &types.Info{
			Types:      make(map[ast.Expr]types.TypeAndValue),
			Defs:       make(map[*ast.Ident]types.Object),
			Uses:       make(map[*ast.Ident]types.Object),
			Implicits:  make(map[ast.Node]types.Object),
			Selections: make(map[*ast.SelectorExpr]*types.Selection),
			Scopes:     make(map[ast.Node]*types.Scope),
		},
		analyses: make(map[*analysis.Analyzer]*analysisEntry),
	}

	// Ignore function bodies for any dependency packages.
	mode := source.ParseFull
	if imp.topLevelPkgID != pkg.id {
		mode = source.ParseExported
	}
	var (
		files []*astFile
		phs   []source.ParseGoHandle
		wg    sync.WaitGroup
	)
	for _, filename := range meta.files {
		uri := span.FileURI(filename)
		f, err := imp.view.getFile(uri)
		if err != nil {
			continue
		}
		ph := imp.view.session.cache.ParseGoHandle(f.Handle(imp.ctx), mode)
		phs = append(phs, ph)
		files = append(files, &astFile{
			uri:       ph.File().Identity().URI,
			isTrimmed: mode == source.ParseExported,
			ph:        ph,
		})
	}
	for i, ph := range phs {
		wg.Add(1)
		go func(i int, ph source.ParseGoHandle) {
			defer wg.Done()

			files[i].file, files[i].err = ph.Parse(imp.ctx)
		}(i, ph)
	}
	wg.Wait()

	for _, f := range files {
		pkg.files = append(pkg.files, f)

		if f.err != nil {
			if f.err == context.Canceled {
				return nil, f.err
			}
			imp.view.session.cache.appendPkgError(pkg, f.err)
		}
	}

	// Use the default type information for the unsafe package.
	if meta.pkgPath == "unsafe" {
		pkg.types = types.Unsafe
	} else if len(files) == 0 { // not the unsafe package, no parsed files
		return nil, fmt.Errorf("no parsed files for package %s", pkg.pkgPath)
	} else {
		pkg.types = types.NewPackage(string(meta.pkgPath), meta.name)
	}

	// Handle circular imports by copying previously seen imports.
	seen := make(map[packageID]struct{})
	for k, v := range imp.seen {
		seen[k] = v
	}
	seen[id] = struct{}{}

	cfg := &types.Config{
		Error: func(err error) {
			imp.view.session.cache.appendPkgError(pkg, err)
		},
		IgnoreFuncBodies: mode == source.ParseExported,
		Importer: &importer{
			view:          imp.view,
			ctx:           imp.ctx,
			fset:          imp.fset,
			topLevelPkgID: imp.topLevelPkgID,
			seen:          seen,
		},
	}
	check := types.NewChecker(cfg, imp.fset, pkg.types, pkg.typesInfo)

	// Ignore type-checking errors.
	check.Files(pkg.GetSyntax())

	// Add every file in this package to our cache.
	imp.cachePackage(imp.ctx, pkg, meta, mode)

	return pkg, nil
}

func (imp *importer) cachePackage(ctx context.Context, pkg *pkg, meta *metadata, mode source.ParseMode) {
	for _, file := range pkg.files {
		f, err := imp.view.getFile(file.uri)
		if err != nil {
			imp.view.session.log.Errorf(ctx, "no file: %v", err)
			continue
		}
		gof, ok := f.(*goFile)
		if !ok {
			imp.view.session.log.Errorf(ctx, "%v is not a Go file", file.uri)
			continue
		}
		if err := imp.cachePerFile(gof, file, pkg); err != nil {
			imp.view.session.log.Errorf(ctx, "failed to cache file %s: %v", gof.URI(), err)
		}
	}

	// Set imports of package to correspond to cached packages.
	// We lock the package cache, but we shouldn't get any inconsistencies
	// because we are still holding the lock on the view.
	for importPath := range meta.children {
		importPkg, err := imp.getPkg(importPath)
		if err != nil {
			continue
		}
		pkg.imports[importPkg.pkgPath] = importPkg
	}
}

func (imp *importer) cachePerFile(gof *goFile, file *astFile, p *pkg) error {
	gof.mu.Lock()
	defer gof.mu.Unlock()

	// Set the package even if we failed to parse the file.
	if gof.pkgs == nil {
		gof.pkgs = make(map[packageID]*pkg)
	}
	gof.pkgs[p.id] = p

	// Get the AST for the file.
	gof.ast = file
	if gof.ast == nil {
		return fmt.Errorf("no AST information for %s", file.uri)
	}
	if gof.ast.file == nil {
		return fmt.Errorf("no AST for %s", file.uri)
	}
	// Get the *token.File directly from the AST.
	pos := gof.ast.file.Pos()
	if !pos.IsValid() {
		return fmt.Errorf("AST for %s has an invalid position", file.uri)
	}
	tok := imp.view.session.cache.FileSet().File(pos)
	if tok == nil {
		return fmt.Errorf("no *token.File for %s", file.uri)
	}
	gof.token = tok
	gof.imports = gof.ast.file.Imports
	return nil
}

func (c *cache) appendPkgError(pkg *pkg, err error) {
	if err == nil {
		return
	}
	var errs []packages.Error
	switch err := err.(type) {
	case *scanner.Error:
		errs = append(errs, packages.Error{
			Pos:  err.Pos.String(),
			Msg:  err.Msg,
			Kind: packages.ParseError,
		})
	case scanner.ErrorList:
		// The first parser error is likely the root cause of the problem.
		if err.Len() > 0 {
			errs = append(errs, packages.Error{
				Pos:  err[0].Pos.String(),
				Msg:  err[0].Msg,
				Kind: packages.ParseError,
			})
		}
	case types.Error:
		errs = append(errs, packages.Error{
			Pos:  c.FileSet().Position(err.Pos).String(),
			Msg:  err.Msg,
			Kind: packages.TypeError,
		})
	}
	pkg.errors = append(pkg.errors, errs...)
}
