// Copyright 2021 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 harnesses

import (
	"os"
	"os/exec"
	"path/filepath"

	"golang.org/x/benchmarks/sweet/common"
	"golang.org/x/benchmarks/sweet/common/log"
)

type Etcd struct{}

func (h Etcd) CheckPrerequisites() error {
	return nil
}

func (h Etcd) Get(srcDir string) error {
	// Build against the latest alpha.
	//
	// Because of the way etcd is released (as a binary blob),
	// deployed copies tend to be stuck with a specific Go version.
	// Improving performance of these versions doesn't really matter.
	// Instead, try to track something close to HEAD.
	return gitShallowClone(
		srcDir,
		"https://github.com/etcd-io/etcd",
		"v3.6.0-alpha.0",
	)
}

func (h Etcd) Build(cfg *common.Config, bcfg *common.BuildConfig) error {
	env := cfg.BuildEnv.Env

	// Add the Go tool to PATH, since etcd's Makefile doesn't provide enough
	// visibility into how etcd is built to allow us to pass this information
	// directly. Also set the GOROOT explicitly because it might have propagated
	// differently from the environment.
	env = env.Prefix("PATH", filepath.Join(cfg.GoRoot, "bin")+":")
	env = env.MustSet("GOROOT=" + cfg.GoRoot)

	cmd := exec.Command("make", "-C", bcfg.SrcDir, "build")
	cmd.Env = env.Collapse()
	log.TraceCommand(cmd, false)
	// Call Output here to get an *ExitError with a populated Stderr field.
	if _, err := cmd.Output(); err != nil {
		return err
	}
	// Note that no matter what we do, the build script insists on putting the
	// binaries into the source directory, so copy the one we care about into
	// BinDir.
	if err := copyFile(filepath.Join(bcfg.BinDir, "etcd"), filepath.Join(bcfg.SrcDir, "bin", "etcd")); err != nil {
		return err
	}
	// Build etcd's benchmarking tool. Our benchmark is just a wrapper around that.
	benchmarkPkg := filepath.Join(bcfg.SrcDir, "tools", "benchmark")
	if err := cfg.GoTool().BuildPath(benchmarkPkg, filepath.Join(bcfg.BinDir, "benchmark")); err != nil {
		return err
	}
	// Build the benchmark wrapper.
	return cfg.GoTool().BuildPath(bcfg.BenchDir, filepath.Join(bcfg.BinDir, "etcd-bench"))
}

func (h Etcd) Run(cfg *common.Config, rcfg *common.RunConfig) error {
	for _, bench := range []string{"put", "stm"} {
		args := append(rcfg.Args, []string{
			"-bench", bench,
			"-etcd-bin", filepath.Join(rcfg.BinDir, "etcd"),
			"-benchmark-bin", filepath.Join(rcfg.BinDir, "benchmark"),
			"-tmp", rcfg.TmpDir,
		}...)
		if rcfg.Short {
			args = append(args, "-short")
		}
		cmd := exec.Command(
			filepath.Join(rcfg.BinDir, "etcd-bench"),
			args...,
		)
		cmd.Env = cfg.ExecEnv.Collapse()
		cmd.Stdout = rcfg.Results
		cmd.Stderr = rcfg.Results
		log.TraceCommand(cmd, false)
		if err := cmd.Run(); err != nil {
			return err
		}
		// Delete tmp because etcd will have written something there and
		// might attempt to reuse it.
		if err := rmDirContents(rcfg.TmpDir); err != nil {
			return err
		}
	}
	return nil
}

func rmDirContents(dir string) error {
	log.CommandPrintf("rm -rf %s/*", dir)
	fs, err := os.ReadDir(dir)
	if err != nil {
		return err
	}
	for _, fi := range fs {
		if err := os.RemoveAll(filepath.Join(dir, fi.Name())); err != nil {
			return err
		}
	}
	return nil
}
