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

import (
	"context"
	"encoding/json"
	"os"
	"runtime"

	"cmd/go/internal/base"
	"cmd/go/internal/cfg"
	"cmd/go/internal/modfetch"
	"cmd/go/internal/modload"

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

var cmdDownload = &base.Command{
	UsageLine: "go mod download [-x] [-json] [modules]",
	Short:     "download modules to local cache",
	Long: `
Download downloads the named modules, which can be module patterns selecting
dependencies of the main module or module queries of the form path@version.
With no arguments, download applies to all dependencies of the main module
(equivalent to 'go mod download all').

The go command will automatically download modules as needed during ordinary
execution. The "go mod download" command is useful mainly for pre-filling
the local cache or to compute the answers for a Go module proxy.

By default, download writes nothing to standard output. It may print progress
messages and errors to standard error.

The -json flag causes download to print a sequence of JSON objects
to standard output, describing each downloaded module (or failure),
corresponding to this Go struct:

    type Module struct {
        Path     string // module path
        Version  string // module version
        Error    string // error loading module
        Info     string // absolute path to cached .info file
        GoMod    string // absolute path to cached .mod file
        Zip      string // absolute path to cached .zip file
        Dir      string // absolute path to cached source root directory
        Sum      string // checksum for path, version (as in go.sum)
        GoModSum string // checksum for go.mod (as in go.sum)
    }

The -x flag causes download to print the commands download executes.

See https://golang.org/ref/mod#go-mod-download for more about 'go mod download'.

See https://golang.org/ref/mod#version-queries for more about version queries.
	`,
}

var downloadJSON = cmdDownload.Flag.Bool("json", false, "")

func init() {
	cmdDownload.Run = runDownload // break init cycle

	// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
	cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
	base.AddModCommonFlags(&cmdDownload.Flag)
	base.AddWorkfileFlag(&cmdDownload.Flag)
}

type moduleJSON struct {
	Path     string `json:",omitempty"`
	Version  string `json:",omitempty"`
	Error    string `json:",omitempty"`
	Info     string `json:",omitempty"`
	GoMod    string `json:",omitempty"`
	Zip      string `json:",omitempty"`
	Dir      string `json:",omitempty"`
	Sum      string `json:",omitempty"`
	GoModSum string `json:",omitempty"`
}

func runDownload(ctx context.Context, cmd *base.Command, args []string) {
	modload.InitWorkfile()

	// Check whether modules are enabled and whether we're in a module.
	modload.ForceUseModules = true
	if !modload.HasModRoot() && len(args) == 0 {
		base.Fatalf("go mod download: no modules specified (see 'go help mod download')")
	}
	haveExplicitArgs := len(args) > 0
	if !haveExplicitArgs {
		args = []string{"all"}
	}
	if modload.HasModRoot() {
		modload.LoadModFile(ctx) // to fill MainModules

		if len(modload.MainModules.Versions()) != 1 {
			panic(modload.TODOWorkspaces("Support workspace mode in go mod download"))
		}
		mainModule := modload.MainModules.Versions()[0]

		targetAtUpgrade := mainModule.Path + "@upgrade"
		targetAtPatch := mainModule.Path + "@patch"
		for _, arg := range args {
			switch arg {
			case mainModule.Path, targetAtUpgrade, targetAtPatch:
				os.Stderr.WriteString("go mod download: skipping argument " + arg + " that resolves to the main module\n")
			}
		}
	}

	downloadModule := func(m *moduleJSON) {
		var err error
		m.Info, err = modfetch.InfoFile(m.Path, m.Version)
		if err != nil {
			m.Error = err.Error()
			return
		}
		m.GoMod, err = modfetch.GoModFile(m.Path, m.Version)
		if err != nil {
			m.Error = err.Error()
			return
		}
		m.GoModSum, err = modfetch.GoModSum(m.Path, m.Version)
		if err != nil {
			m.Error = err.Error()
			return
		}
		mod := module.Version{Path: m.Path, Version: m.Version}
		m.Zip, err = modfetch.DownloadZip(ctx, mod)
		if err != nil {
			m.Error = err.Error()
			return
		}
		m.Sum = modfetch.Sum(mod)
		m.Dir, err = modfetch.Download(ctx, mod)
		if err != nil {
			m.Error = err.Error()
			return
		}
	}

	var mods []*moduleJSON
	type token struct{}
	sem := make(chan token, runtime.GOMAXPROCS(0))
	infos, infosErr := modload.ListModules(ctx, args, 0)
	if !haveExplicitArgs {
		// 'go mod download' is sometimes run without arguments to pre-populate the
		// module cache. It may fetch modules that aren't needed to build packages
		// in the main mdoule. This is usually not intended, so don't save sums for
		// downloaded modules (golang.org/issue/45332).
		// TODO(golang.org/issue/45551): For now, in ListModules, save sums needed
		// to load the build list (same as 1.15 behavior). In the future, report an
		// error if go.mod or go.sum need to be updated after loading the build
		// list.
		modload.DisallowWriteGoMod()
	}

	for _, info := range infos {
		if info.Replace != nil {
			info = info.Replace
		}
		if info.Version == "" && info.Error == nil {
			// main module or module replaced with file path.
			// Nothing to download.
			continue
		}
		m := &moduleJSON{
			Path:    info.Path,
			Version: info.Version,
		}
		mods = append(mods, m)
		if info.Error != nil {
			m.Error = info.Error.Err
			continue
		}
		sem <- token{}
		go func() {
			downloadModule(m)
			<-sem
		}()
	}

	// Fill semaphore channel to wait for goroutines to finish.
	for n := cap(sem); n > 0; n-- {
		sem <- token{}
	}

	if *downloadJSON {
		for _, m := range mods {
			b, err := json.MarshalIndent(m, "", "\t")
			if err != nil {
				base.Fatalf("go mod download: %v", err)
			}
			os.Stdout.Write(append(b, '\n'))
			if m.Error != "" {
				base.SetExitStatus(1)
			}
		}
	} else {
		for _, m := range mods {
			if m.Error != "" {
				base.Errorf("go mod download: %v", m.Error)
			}
		}
		base.ExitIfErrors()
	}

	// If there were explicit arguments, update go.mod and especially go.sum.
	// 'go mod download mod@version' is a useful way to add a sum without using
	// 'go get mod@version', which may have other side effects. We print this in
	// some error message hints.
	//
	// Don't save sums for 'go mod download' without arguments; see comment above.
	if haveExplicitArgs {
		modload.WriteGoMod(ctx)
	}

	// If there was an error matching some of the requested packages, emit it now
	// (after we've written the checksums for the modules that were downloaded
	// successfully).
	if infosErr != nil {
		base.Errorf("go mod download: %v", infosErr)
	}
}
