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

import (
	"context"
	"errors"
	"fmt"
	"os"
	"runtime"
	"strings"

	"cmd/go/internal/base"
	"cmd/go/internal/cfg"
	"cmd/go/internal/modinfo"
	"cmd/go/internal/search"

	"golang.org/x/mod/module"
)

type ListMode int

const (
	ListU ListMode = 1 << iota
	ListRetracted
	ListDeprecated
	ListVersions
	ListRetractedVersions
)

// ListModules returns a description of the modules matching args, if known,
// along with any error preventing additional matches from being identified.
//
// The returned slice can be nonempty even if the error is non-nil.
func ListModules(ctx context.Context, args []string, mode ListMode) ([]*modinfo.ModulePublic, error) {
	rs, mods, err := listModules(ctx, LoadModFile(ctx), args, mode)

	type token struct{}
	sem := make(chan token, runtime.GOMAXPROCS(0))
	if mode != 0 {
		for _, m := range mods {
			add := func(m *modinfo.ModulePublic) {
				sem <- token{}
				go func() {
					if mode&ListU != 0 {
						addUpdate(ctx, m)
					}
					if mode&ListVersions != 0 {
						addVersions(ctx, m, mode&ListRetractedVersions != 0)
					}
					if mode&ListRetracted != 0 {
						addRetraction(ctx, m)
					}
					if mode&ListDeprecated != 0 {
						addDeprecation(ctx, m)
					}
					<-sem
				}()
			}

			add(m)
			if m.Replace != nil {
				add(m.Replace)
			}
		}
	}
	// Fill semaphore channel to wait for all tasks to finish.
	for n := cap(sem); n > 0; n-- {
		sem <- token{}
	}

	if err == nil {
		commitRequirements(ctx, rs)
	}
	return mods, err
}

func listModules(ctx context.Context, rs *Requirements, args []string, mode ListMode) (_ *Requirements, mods []*modinfo.ModulePublic, mgErr error) {
	if len(args) == 0 {
		var ms []*modinfo.ModulePublic
		for _, m := range MainModules.Versions() {
			ms = append(ms, moduleInfo(ctx, rs, m, mode))
		}
		return rs, ms, nil
	}

	needFullGraph := false
	for _, arg := range args {
		if strings.Contains(arg, `\`) {
			base.Fatalf("go: module paths never use backslash")
		}
		if search.IsRelativePath(arg) {
			base.Fatalf("go: cannot use relative path %s to specify module", arg)
		}
		if arg == "all" || strings.Contains(arg, "...") {
			needFullGraph = true
			if !HasModRoot() {
				base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
			}
			continue
		}
		if i := strings.Index(arg, "@"); i >= 0 {
			path := arg[:i]
			vers := arg[i+1:]
			if vers == "upgrade" || vers == "patch" {
				if _, ok := rs.rootSelected(path); !ok || rs.pruning == unpruned {
					needFullGraph = true
					if !HasModRoot() {
						base.Fatalf("go: cannot match %q: %v", arg, ErrNoModRoot)
					}
				}
			}
			continue
		}
		if _, ok := rs.rootSelected(arg); !ok || rs.pruning == unpruned {
			needFullGraph = true
			if mode&ListVersions == 0 && !HasModRoot() {
				base.Fatalf("go: cannot match %q without -versions or an explicit version: %v", arg, ErrNoModRoot)
			}
		}
	}

	var mg *ModuleGraph
	if needFullGraph {
		rs, mg, mgErr = expandGraph(ctx, rs)
	}

	matchedModule := map[module.Version]bool{}
	for _, arg := range args {
		if i := strings.Index(arg, "@"); i >= 0 {
			path := arg[:i]
			vers := arg[i+1:]

			var current string
			if mg == nil {
				current, _ = rs.rootSelected(path)
			} else {
				current = mg.Selected(path)
			}
			if current == "none" && mgErr != nil {
				if vers == "upgrade" || vers == "patch" {
					// The module graph is incomplete, so we don't know what version we're
					// actually upgrading from.
					// mgErr is already set, so just skip this module.
					continue
				}
			}

			allowed := CheckAllowed
			if IsRevisionQuery(vers) || mode&ListRetracted != 0 {
				// Allow excluded and retracted versions if the user asked for a
				// specific revision or used 'go list -retracted'.
				allowed = nil
			}
			info, err := Query(ctx, path, vers, current, allowed)
			if err != nil {
				mods = append(mods, &modinfo.ModulePublic{
					Path:    path,
					Version: vers,
					Error:   modinfoError(path, vers, err),
				})
				continue
			}

			// Indicate that m was resolved from outside of rs by passing a nil
			// *Requirements instead.
			var noRS *Requirements

			mod := moduleInfo(ctx, noRS, module.Version{Path: path, Version: info.Version}, mode)
			mods = append(mods, mod)
			continue
		}

		// Module path or pattern.
		var match func(string) bool
		if arg == "all" {
			match = func(string) bool { return true }
		} else if strings.Contains(arg, "...") {
			match = search.MatchPattern(arg)
		} else {
			var v string
			if mg == nil {
				var ok bool
				v, ok = rs.rootSelected(arg)
				if !ok {
					// We checked rootSelected(arg) in the earlier args loop, so if there
					// is no such root we should have loaded a non-nil mg.
					panic(fmt.Sprintf("internal error: root requirement expected but not found for %v", arg))
				}
			} else {
				v = mg.Selected(arg)
			}
			if v == "none" && mgErr != nil {
				// mgErr is already set, so just skip this module.
				continue
			}
			if v != "none" {
				mods = append(mods, moduleInfo(ctx, rs, module.Version{Path: arg, Version: v}, mode))
			} else if cfg.BuildMod == "vendor" {
				// In vendor mode, we can't determine whether a missing module is “a
				// known dependency” because the module graph is incomplete.
				// Give a more explicit error message.
				mods = append(mods, &modinfo.ModulePublic{
					Path:  arg,
					Error: modinfoError(arg, "", errors.New("can't resolve module using the vendor directory\n\t(Use -mod=mod or -mod=readonly to bypass.)")),
				})
			} else if mode&ListVersions != 0 {
				// Don't make the user provide an explicit '@latest' when they're
				// explicitly asking what the available versions are. Instead, return a
				// module with version "none", to which we can add the requested list.
				mods = append(mods, &modinfo.ModulePublic{Path: arg})
			} else {
				mods = append(mods, &modinfo.ModulePublic{
					Path:  arg,
					Error: modinfoError(arg, "", errors.New("not a known dependency")),
				})
			}
			continue
		}

		matched := false
		for _, m := range mg.BuildList() {
			if match(m.Path) {
				matched = true
				if !matchedModule[m] {
					matchedModule[m] = true
					mods = append(mods, moduleInfo(ctx, rs, m, mode))
				}
			}
		}
		if !matched {
			fmt.Fprintf(os.Stderr, "warning: pattern %q matched no module dependencies\n", arg)
		}
	}

	return rs, mods, mgErr
}

// modinfoError wraps an error to create an error message in
// modinfo.ModuleError with minimal redundancy.
func modinfoError(path, vers string, err error) *modinfo.ModuleError {
	var nerr *NoMatchingVersionError
	var merr *module.ModuleError
	if errors.As(err, &nerr) {
		// NoMatchingVersionError contains the query, so we don't mention the
		// query again in ModuleError.
		err = &module.ModuleError{Path: path, Err: err}
	} else if !errors.As(err, &merr) {
		// If the error does not contain path and version, wrap it in a
		// module.ModuleError.
		err = &module.ModuleError{Path: path, Version: vers, Err: err}
	}

	return &modinfo.ModuleError{Err: err.Error()}
}
