// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Command gendoc can be used for generating detailed godoc comments for
// cmdline-based tools.  The user specifies the cmdline-based tool source file
// directory <dir> using the first command-line argument and gendoc executes the
// tool with flags that generate detailed godoc comment and output it to
// <dir>/doc.go.  If more than one command-line argument is provided, they are
// passed through to the tool the gendoc executes.
//
// NOTE: The reason this command is located under a testdata directory is to
// enforce its idiomatic use through "go run <path>/testdata/gendoc.go <dir>
// [args]".
//
// NOTE: The gendoc command itself is not based on the cmdline library to avoid
// non-trivial bootstrapping.  In particular, if the compilation of gendoc
// requires GOPATH to contain the vanadium Go workspaces, then running the
// gendoc command requires the jiri tool, which in turn may depend on the
// gendoc command.
package main

import (
	"bytes"
	"flag"
	"fmt"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"strings"
)

var flagTags string

func main() {
	flag.StringVar(&flagTags, "tags", "", "Tags for go build, also added as build constraints in the generated doc.go.")
	flag.Parse()
	if err := generate(flag.Args()); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}

func generate(args []string) error {
	if got, want := len(args), 1; got < want {
		return fmt.Errorf("gendoc requires at least one argument\nusage: gendoc <dir> [args]")
	}
	pkg, args := args[0], args[1:]

	// Find out the binary name from the pkg name.
	var listOut bytes.Buffer
	listCmd := exec.Command("go", "list")
	listCmd.Stdout = &listOut
	if err := listCmd.Run(); err != nil {
		return fmt.Errorf("%q failed: %v\n%v\n", strings.Join(listCmd.Args, " "), err, listOut.String())
	}
	binName := filepath.Base(strings.TrimSpace(listOut.String()))

	// Install the gendoc binary in a temporary folder.
	tmpDir, err := ioutil.TempDir("", "")
	if err != nil {
		return fmt.Errorf("TempDir() failed: %v", err)
	}
	defer os.RemoveAll(tmpDir)
	gendocBin := filepath.Join(tmpDir, binName)
	env := environ()
	env = append(env, "GOBIN="+tmpDir)
	installArgs := []string{"go", "install", "-tags=" + flagTags, pkg}
	installCmd := exec.Command("jiri", installArgs...)
	installCmd.Env = env
	if err := installCmd.Run(); err != nil {
		return fmt.Errorf("%q failed: %v\n", strings.Join(installCmd.Args, " "), err)
	}

	// Use it to generate the documentation.
	var tagsConstraint string
	if flagTags != "" {
		tagsConstraint = fmt.Sprintf("// +build %s\n\n", flagTags)
	}
	var out bytes.Buffer
	if len(args) == 0 {
		args = []string{"help", "..."}
	}
	runCmd := exec.Command(gendocBin, args...)
	runCmd.Stdout = &out
	runCmd.Env = environ()
	if err := runCmd.Run(); err != nil {
		return fmt.Errorf("%q failed: %v\n%v\n", strings.Join(runCmd.Args, " "), err, out.String())
	}
	doc := fmt.Sprintf(`// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file was auto-generated via go generate.
// DO NOT UPDATE MANUALLY

%s/*
%s*/
package main
`, tagsConstraint, suppressParallelFlag(out.String()))

	// Write the result to doc.go.
	path, perm := filepath.Join(pkg, "doc.go"), os.FileMode(0644)
	if err := ioutil.WriteFile(path, []byte(doc), perm); err != nil {
		return fmt.Errorf("WriteFile(%v, %v) failed: %v\n", path, perm, err)
	}
	return nil
}

// suppressParallelFlag replaces the default value of the test.parallel flag
// with the literal string "<number of threads>". The default value of the
// test.parallel flag is GOMAXPROCS, which (since Go1.5) is set to the number
// of logical CPU threads on the current system. This causes problems with the
// vanadium-go-generate test, which requires that the output of gendoc is the
// same on all systems.
func suppressParallelFlag(input string) string {
	pattern := regexp.MustCompile("(?m:(^ -test\\.parallel=)(?:\\d)+$)")
	return pattern.ReplaceAllString(input, "$1<number of threads>")
}

// environ returns the environment variables to use when running the command to
// retrieve full help information.
func environ() []string {
	var env []string
	for _, e := range os.Environ() {
		// Strip out all existing CMDLINE_* envvars to start with a clean slate.
		// E.g. otherwise if CMDLINE_PREFIX is set, it'll taint all of the output.
		if !strings.HasPrefix(e, "CMDLINE_") {
			env = append(env, e)
		}
	}
	// We want the godoc style for our generated documentation.
	env = append(env, "CMDLINE_STYLE=godoc")
	return env
}
