// Copyright 2016 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.

// The following enables go generate to generate the doc.go file.
//go:generate go run $JIRI_ROOT/release/go/src/v.io/x/lib/cmdline/testdata/gendoc.go . -help

package main

import (
	"bytes"
	"fmt"
	"io"
	"os"
	"strings"

	"v.io/v23/vdl"
	"v.io/v23/vdl/vdltest"
	"v.io/v23/vom"
	"v.io/x/lib/cmdline"
	"v.io/x/lib/textutil"
	"v.io/x/ref/lib/vdl/codegen"
	"v.io/x/ref/lib/vdl/codegen/vdlgen"
)

var cmdGen = &cmdline.Command{
	Runner: cmdline.RunnerFunc(runGen),
	Name:   "vomtestgen",
	Short:  "generates test data for the vomtest package",
	Long: `
Command vomtestgen generates test cases for the vomtest package.  The following
file is generated:

   data81_gen.vdl - Golden file containing test cases.

This tool does not run the vdl tool on the generated *.vdl files; you must do
that yourself, typically via "jiri go install".

Instead of running this tool manually, it is typically invoked via:

   $ jiri run go generate v.io/v23/vom/vomtest
`,
}

func main() {
	cmdGen.Flags.StringVar(&flagData81, "data81", "data81_gen.vdl", "Name of the generated data file for version 81.")
	cmdline.Main(cmdGen)
}

var (
	flagData81 string
)

func runGen(_ *cmdline.Env, _ []string) error {
	allCanonical := vdltest.AllPassFunc(func(e vdltest.Entry) bool {
		return e.IsCanonical
	})
	writeFileVomTest(flagData81, "data81", vdltest.ToEntryValues(allCanonical))
	return nil
}

// This tool is only used to generate test cases for the vdltest package, so the
// strategy is to panic on any error, to make the code simpler.
func panicOnError(err error) {
	if err != nil {
		panic(err)
	}
}

func createFile(name string) (*os.File, func()) {
	file, err := os.Create(name)
	panicOnError(err)
	return file, func() { panicOnError(file.Close()) }
}

func writef(w io.Writer, format string, args ...interface{}) {
	_, err := fmt.Fprintf(w, format, args...)
	panicOnError(err)
}

func writeHeader(w io.Writer) {
	writef(w, `// Copyright 2016 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 by v.io/v23/vom/vomtest/internal/vomtestgen
// Run the following to re-generate:
//   $ jiri run go generate v.io/v23/vom/vomtest

package vomtest

`)
}

func writeFileVomTest(fileName, constName string, entries []vdltest.EntryValue) {
	const version vom.Version = vom.Version81
	// We skip all random entries for now, since they may contain multiple set and
	// map elements, which would cause non-deterministic output.
	//
	// TODO(toddw): Determine a better strategy.
	var filtered []vdltest.EntryValue
	for _, e := range entries {
		if !strings.HasPrefix(e.Label, "Random") {
			filtered = append(filtered, e)
		}
	}
	skipped := len(entries) - len(filtered)
	entries = filtered

	fmt.Printf("Writing %s:\t%d entries (%d skipped)\n", fileName, len(entries), skipped)
	file, cleanup := createFile(fileName)
	defer cleanup()
	writeHeader(file)
	imports := codegen.Imports{
		{Path: "v.io/v23/vdl/vdltest", Local: "vdltest"},
	}
	writef(file, "%s\n\n", vdlgen.Imports(imports))
	comment := textutil.PrefixLineWriter(file, "// ")
	panicOnError(vdltest.PrintEntryStats(comment, entries...))
	panicOnError(comment.Flush())
	writef(file, "\nconst %[1]s = []TestCase {\n", constName)
	for _, e := range entries {
		source := vdlgen.TypedConst(e.Source, "v.io/v23/vom/vomtest", imports)
		hexVersion, hexType, hexValue, vomDump := toVomHex(version, e.Source)
		writef(file, `%[1]s
	{
		%#[2]q,
		%[3]s,
		0x%[4]x,
		%[5]q, %[6]q, %[7]q,
	},
`, vomDump, e.Label+" "+source, source, byte(version), hexVersion+hexType+hexValue, hexType, hexValue)
	}
	writef(file, "}\n")
}

func toVomHex(version vom.Version, value *vdl.Value) (_, _, _, _ string) {
	var buf, bufType bytes.Buffer
	encType := vom.NewVersionedTypeEncoder(version, &bufType)
	enc := vom.NewVersionedEncoderWithTypeEncoder(version, &buf, encType)
	panicOnError(enc.Encode(value))
	versionByte, _ := buf.ReadByte() // Read the version byte.
	if bufType.Len() > 0 {
		bufType.ReadByte() // Remove the version byte.
	}
	vomBytes := append([]byte{versionByte}, bufType.Bytes()...)
	vomBytes = append(vomBytes, buf.Bytes()...)
	dump, err := vom.Dump(vomBytes)
	panicOnError(err)
	const pre = "\t// "
	vomDump := pre + strings.Replace(dump, "\n", "\n"+pre, -1)
	if strings.HasSuffix(vomDump, "\n"+pre) {
		vomDump = vomDump[:len(vomDump)-len("\n"+pre)]
	}
	return fmt.Sprintf("%x", versionByte), fmt.Sprintf("%x", bufType.Bytes()), fmt.Sprintf("%x", buf.Bytes()), vomDump
}
