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

	"golang.org/x/tools/internal/lsp/source"
	"golang.org/x/tools/internal/lsp/telemetry"
	"golang.org/x/tools/internal/span"
	errors "golang.org/x/xerrors"
)

func (v *view) CheckPackageHandles(ctx context.Context, f source.File) (source.Snapshot, []source.CheckPackageHandle, error) {
	// Get the snapshot that will be used for type-checking.
	s := v.getSnapshot()

	cphs, err := s.CheckPackageHandles(ctx, f)
	if err != nil {
		return nil, nil, err
	}
	if len(cphs) == 0 {
		return nil, nil, errors.Errorf("no CheckPackageHandles for %s", f.URI())
	}
	return s, cphs, nil
}

func (s *snapshot) CheckPackageHandles(ctx context.Context, f source.File) ([]source.CheckPackageHandle, error) {
	ctx = telemetry.File.With(ctx, f.URI())

	fh := s.Handle(ctx, f)

	// Determine if we need to type-check the package.
	m, cphs, load, check := s.shouldCheck(fh)

	// We may need to re-load package metadata.
	// We only need to this if it has been invalidated, and is therefore unvailable.
	if load {
		var err error
		m, err = s.load(ctx, f.URI())
		if err != nil {
			return nil, err
		}
		// If load has explicitly returned nil metadata and no error,
		// it means that we should not re-type-check the packages.
		if m == nil {
			return cphs, nil
		}
	}
	if check {
		var results []source.CheckPackageHandle
		for _, m := range m {
			cph, err := s.checkPackageHandle(ctx, m.id, source.ParseFull)
			if err != nil {
				return nil, err
			}
			results = append(results, cph)
		}
		cphs = results
	}
	if len(cphs) == 0 {
		return nil, errors.Errorf("no CheckPackageHandles for %s", f.URI())
	}
	return cphs, nil
}

func (s *snapshot) shouldCheck(fh source.FileHandle) (m []*metadata, cphs []source.CheckPackageHandle, load, check bool) {
	// Get the metadata for the given file.
	m = s.getMetadataForURI(fh.Identity().URI)

	// If there is no metadata for the package, we definitely need to type-check again.
	if len(m) == 0 {
		return nil, nil, true, true
	}

	// If the metadata for the package had missing dependencies,
	// we _may_ need to re-check. If the missing dependencies haven't changed
	// since previous load, we will not check again.
	for _, m := range m {
		if len(m.missingDeps) != 0 {
			load = true
			check = true
		}
	}
	// We expect to see a checked package for each package ID,
	// and it should be parsed in full mode.
	cphs = s.getPackages(fh.Identity().URI, source.ParseFull)
	if len(cphs) < len(m) {
		return m, nil, load, true
	}
	return m, cphs, load, check
}

func (v *view) GetActiveReverseDeps(ctx context.Context, f source.File) (results []source.CheckPackageHandle) {
	var (
		s     = v.getSnapshot()
		rdeps = transitiveReverseDependencies(ctx, f.URI(), s)
		files = v.openFiles(ctx, rdeps)
		seen  = make(map[span.URI]struct{})
	)
	for _, f := range files {
		if _, ok := seen[f.URI()]; ok {
			continue
		}
		cphs, err := s.CheckPackageHandles(ctx, f)
		if err != nil {
			continue
		}
		cph, err := source.WidestCheckPackageHandle(cphs)
		if err != nil {
			continue
		}
		for _, ph := range cph.Files() {
			seen[ph.File().Identity().URI] = struct{}{}
		}
		results = append(results, cph)
	}
	return results
}

func transitiveReverseDependencies(ctx context.Context, uri span.URI, s *snapshot) (result []span.URI) {
	var (
		seen         = make(map[packageID]struct{})
		uris         = make(map[span.URI]struct{})
		topLevelURIs = make(map[span.URI]struct{})
	)

	metadata := s.getMetadataForURI(uri)

	for _, m := range metadata {
		for _, uri := range m.files {
			topLevelURIs[uri] = struct{}{}
		}
		s.reverseDependencies(m.id, uris, seen)
	}
	// Filter out the URIs that belong to the original package.
	for uri := range uris {
		if _, ok := topLevelURIs[uri]; ok {
			continue
		}
		result = append(result, uri)
	}
	return result
}
