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

import (
	"archive/zip"
	"bytes"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"regexp"

	"golang.org/x/tools/go/packages"
)

// Modules is the exporter that produces module layouts.
// Each "repository" is put in it's own module, and the module file generated
// will have replace directives for all other modules.
// Given the two files
//     golang.org/repoa#a/a.go
//     golang.org/repob#b/b.go
// You would get the directory layout
//     /sometemporarydirectory
//     ├── repoa
//     │   ├── a
//     │   │   └── a.go
//     │   └── go.mod
//     └── repob
//         ├── b
//         │   └── b.go
//         └── go.mod
// and the working directory would be
//     /sometemporarydirectory/repoa
var Modules = modules{}

type modules struct{}

func (modules) Name() string {
	return "Modules"
}

func (modules) Filename(exported *Exported, module, fragment string) string {
	if module == exported.primary {
		return filepath.Join(primaryDir(exported), fragment)
	}
	return filepath.Join(moduleDir(exported, module), fragment)
}

func (modules) Finalize(exported *Exported) error {
	// Write out the primary module. This module can use symlinks and
	// other weird stuff, and will be the working dir for the go command.
	// It depends on all the other modules.
	primaryDir := primaryDir(exported)
	exported.Config.Dir = primaryDir
	exported.written[exported.primary]["go.mod"] = filepath.Join(primaryDir, "go.mod")
	primaryGomod := "module " + exported.primary + "\nrequire (\n"
	for other := range exported.written {
		if other == exported.primary {
			continue
		}
		primaryGomod += fmt.Sprintf("\t%v %v\n", other, moduleVersion(other))
	}
	primaryGomod += ")\n"
	if err := ioutil.WriteFile(filepath.Join(primaryDir, "go.mod"), []byte(primaryGomod), 0644); err != nil {
		return err
	}

	// Create the mod cache so we can rename it later, even if we don't need it.
	if err := os.MkdirAll(modCache(exported), 0755); err != nil {
		return err
	}

	// Write out the go.mod files for the other modules.
	for module, files := range exported.written {
		if module == exported.primary {
			continue
		}
		dir := moduleDir(exported, module)

		modfile := filepath.Join(dir, "go.mod")
		if err := ioutil.WriteFile(modfile, []byte("module "+module+"\n"), 0644); err != nil {
			return err
		}
		files["go.mod"] = modfile
	}

	// Zip up all the secondary modules into the proxy dir.
	proxyDir := filepath.Join(exported.temp, "modproxy")
	for module, files := range exported.written {
		if module == exported.primary {
			continue
		}
		dir := filepath.Join(proxyDir, module, "@v")

		if err := writeModuleProxy(dir, module, files); err != nil {
			return fmt.Errorf("creating module proxy dir for %v: %v", module, err)
		}
	}

	// Discard the original mod cache dir, which contained the files written
	// for us by Export.
	if err := os.Rename(modCache(exported), modCache(exported)+".orig"); err != nil {
		return err
	}
	exported.Config.Env = append(exported.Config.Env,
		"GO111MODULE=on",
		"GOPATH="+filepath.Join(exported.temp, "modcache"),
		"GOPROXY="+proxyDirToURL(proxyDir))

	// Run go mod download to recreate the mod cache dir with all the extra
	// stuff in cache. All the files created by Export should be recreated.
	if err := invokeGo(exported.Config, "mod", "download"); err != nil {
		return err
	}

	return nil
}

// writeModuleProxy creates a directory in the proxy dir for a module.
func writeModuleProxy(dir, module string, files map[string]string) error {
	ver := moduleVersion(module)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return err
	}

	// list file. Just the single version.
	if err := ioutil.WriteFile(filepath.Join(dir, "list"), []byte(ver+"\n"), 0644); err != nil {
		return err
	}

	// go.mod, copied from the file written in Finalize.
	modContents, err := ioutil.ReadFile(files["go.mod"])
	if err != nil {
		return err
	}
	if err := ioutil.WriteFile(filepath.Join(dir, ver+".mod"), modContents, 0644); err != nil {
		return err
	}

	// info file, just the bare bones.
	infoContents := []byte(fmt.Sprintf(`{"Version": "%v", "Time":"2017-12-14T13:08:43Z"}`, ver))
	if err := ioutil.WriteFile(filepath.Join(dir, ver+".info"), infoContents, 0644); err != nil {
		return err
	}

	// zip of all the source files.
	f, err := os.OpenFile(filepath.Join(dir, ver+".zip"), os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		return err
	}
	z := zip.NewWriter(f)
	for name, path := range files {
		zf, err := z.Create(module + "@" + ver + "/" + name)
		if err != nil {
			return err
		}
		contents, err := ioutil.ReadFile(path)
		if err != nil {
			return err
		}
		if _, err := zf.Write(contents); err != nil {
			return err
		}
	}
	if err := z.Close(); err != nil {
		return err
	}
	if err := f.Close(); err != nil {
		return err
	}

	return nil
}

func invokeGo(cfg *packages.Config, args ...string) error {
	stdout := new(bytes.Buffer)
	stderr := new(bytes.Buffer)
	cmd := exec.Command("go", args...)
	cmd.Env = append(append([]string{}, cfg.Env...), "PWD="+cfg.Dir)
	cmd.Dir = cfg.Dir
	cmd.Stdout = stdout
	cmd.Stderr = stderr
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("go %v: %s: %s", args, err, stderr)
	}
	return nil
}

func modCache(exported *Exported) string {
	return filepath.Join(exported.temp, "modcache/pkg/mod")
}

func primaryDir(exported *Exported) string {
	return filepath.Join(exported.temp, "primarymod", path.Base(exported.primary))
}

func moduleDir(exported *Exported, module string) string {
	return filepath.Join(modCache(exported), path.Dir(module), path.Base(module)+"@"+moduleVersion(module))
}

var versionSuffixRE = regexp.MustCompile(`v\d+`)

func moduleVersion(module string) string {
	if versionSuffixRE.MatchString(path.Base(module)) {
		return path.Base(module) + ".0.0"
	}
	return "v1.0.0"
}
