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

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"

	"cmd/go/internal/base"
	"cmd/go/internal/module"
)

var CmdVendor = &base.Command{
	UsageLine: "vendor [-v]",
	Short:     "vendor dependencies of current module",
	Long: `
Vendor resets the module's vendor directory to include all
packages needed to build and test all packages in the module
and their dependencies.

The -v flag causes vendor to print to standard error the
module paths of the modules processed and the import paths
of the packages copied.
	`,
}

var vendorV = CmdVendor.Flag.Bool("v", false, "")
var copiedDir map[string]bool

func init() {
	CmdVendor.Run = runVendor // break init cycle
}

func runVendor(cmd *base.Command, args []string) {
	if Init(); !Enabled() {
		base.Fatalf("vgo vendor: cannot use -m outside module")
	}
	if len(args) != 0 {
		base.Fatalf("vgo vendor: vendor takes no arguments")
	}
	InitMod()
	pkgs := ImportPaths([]string{"ALL"})

	vdir := filepath.Join(ModRoot, "vendor")
	if err := os.RemoveAll(vdir); err != nil {
		base.Fatalf("vgo vendor: %v", err)
	}

	modpkgs := make(map[module.Version][]string)
	for _, pkg := range pkgs {
		m := pkgmod[pkg]
		if m == Target {
			continue
		}
		modpkgs[m] = append(modpkgs[m], pkg)
	}

	var buf bytes.Buffer
	copiedDir = make(map[string]bool)
	for _, m := range buildList[1:] {
		if pkgs := modpkgs[m]; len(pkgs) > 0 {
			repl := ""
			if r := replaced(m); r != nil {
				repl = " => " + r.New.Path
				if r.New.Version != "" {
					repl += " " + r.New.Version
				}
			}
			fmt.Fprintf(&buf, "# %s %s%s\n", m.Path, m.Version, repl)
			if *vendorV {
				fmt.Fprintf(os.Stderr, "# %s %s%s\n", m.Path, m.Version, repl)
			}
			for _, pkg := range pkgs {
				fmt.Fprintf(&buf, "%s\n", pkg)
				if *vendorV {
					fmt.Fprintf(os.Stderr, "%s\n", pkg)
				}
				vendorPkg(vdir, pkg)
			}
		}
	}
	if buf.Len() == 0 {
		fmt.Fprintf(os.Stderr, "vgo: no dependencies to vendor\n")
		return
	}
	if err := ioutil.WriteFile(filepath.Join(vdir, "vgo.list"), buf.Bytes(), 0666); err != nil {
		base.Fatalf("vgo vendor: %v", err)
	}
}

func vendorPkg(vdir, pkg string) {
	realPath := importmap[pkg]
	if realPath != pkg && importmap[realPath] != "" {
		fmt.Fprintf(os.Stderr, "warning: %s imported as both %s and %s; making two copies.\n", realPath, realPath, pkg)
	}

	dst := filepath.Join(vdir, pkg)
	src := pkgdir[realPath]
	if src == "" {
		fmt.Fprintf(os.Stderr, "internal error: no pkg for %s -> %s\n", pkg, realPath)
	}

	copyDir(dst, src, false)
	if mod, ok := pkgmod[pkg]; ok {
		copyTestdata(mod.Path, pkg, dst, src)
	}
}

// Copy the testdata directories in parent directories.
// If the package being vendored is a/b/c,
// try to copy a/b/c/testdata, a/b/testdata and a/testdata to vendor directory,
// up to the module root.
func copyTestdata(modPath, pkg, dst, src string) {
	testdata := func(dir string) string {
		return filepath.Join(dir, "testdata")
	}
	for {
		if copiedDir[dst] {
			break
		}
		copiedDir[dst] = true
		if info, err := os.Stat(testdata(src)); err == nil && info.IsDir() {
			copyDir(testdata(dst), testdata(src), true)
		}
		if modPath == pkg {
			break
		}
		pkg = filepath.Dir(pkg)
		dst = filepath.Dir(dst)
		src = filepath.Dir(src)
	}
}

func copyDir(dst, src string, recursive bool) {
	files, err := ioutil.ReadDir(src)
	if err != nil {
		base.Fatalf("vgo vendor: %v", err)
	}
	if err := os.MkdirAll(dst, 0777); err != nil {
		base.Fatalf("vgo vendor: %v", err)
	}
	for _, file := range files {
		if file.IsDir() {
			if recursive || file.Name() == "testdata" {
				copyDir(filepath.Join(dst, file.Name()), filepath.Join(src, file.Name()), true)
			}
			continue
		}
		if !file.Mode().IsRegular() {
			continue
		}
		r, err := os.Open(filepath.Join(src, file.Name()))
		if err != nil {
			base.Fatalf("vgo vendor: %v", err)
		}
		w, err := os.Create(filepath.Join(dst, file.Name()))
		if err != nil {
			base.Fatalf("vgo vendor: %v", err)
		}
		if _, err := io.Copy(w, r); err != nil {
			base.Fatalf("vgo vendor: %v", err)
		}
		r.Close()
		if err := w.Close(); err != nil {
			base.Fatalf("vgo vendor: %v", err)
		}
	}
}

// hasPathPrefix reports whether the path s begins with the
// elements in prefix.
func hasPathPrefix(s, prefix string) bool {
	switch {
	default:
		return false
	case len(s) == len(prefix):
		return s == prefix
	case len(s) > len(prefix):
		if prefix != "" && prefix[len(prefix)-1] == '/' {
			return strings.HasPrefix(s, prefix)
		}
		return s[len(prefix)] == '/' && s[:len(prefix)] == prefix
	}
}
