// Program makeset generates source code for a set package.  The type of the
// elements of the set is determined by a TOML configuration stored in a file
// named by the -config flag.
//
// Usage:
//   go run makeset.go -output $DIR -config config.toml
//
package main

//go:generate go run github.com/creachadair/staticfile/compiledata -pkg main -out static.go *.go.in

import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"go/format"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"text/template"

	"github.com/BurntSushi/toml"
	"github.com/creachadair/staticfile"
)

// A Config describes the nature of the set to be constructed.
type Config struct {
	// A human-readable description of the set this config defines.
	// This is ignored by the code generator, but may serve as documentation.
	Desc string

	// The name of the resulting set package, e.g., "intset" (required).
	Package string

	// The name of the type contained in the set, e.g., "int" (required).
	Type string

	// The spelling of the zero value for the set type, e.g., "0" (required).
	Zero string

	// If set, a type definition is added to the package mapping Type to this
	// structure, e.g., "struct { ... }". You may prefix Decl with "=" to
	// generate a type alias (this requires Go ≥ 1.9).
	Decl string

	// If set, the body of a function with signature func(x, y Type) bool
	// reporting whether x is less than y.
	//
	// For example:
	//   if x[0] == y[0] {
	//     return x[1] < y[1]
	//   }
	//   return x[0] < y[0]
	Less string

	// If set, the body of a function with signature func(x Type) string that
	// converts x to a human-readable string.
	//
	// For example:
	//   return strconv.Itoa(x)
	ToString string

	// If set, additional packages to import in the generated code.
	Imports []string

	// If set, additional packages to import in the test.
	TestImports []string

	// If true, include transformations, e.g., Map, Partition, Each.
	Transforms bool

	// A list of exactly ten ordered test values used for the construction of
	// unit tests. If omitted, unit tests are not generated.
	TestValues []interface{} `json:"testValues,omitempty"`
}

func (c *Config) validate() error {
	if c.Package == "" {
		return errors.New("invalid: missing package name")
	} else if c.Type == "" {
		return errors.New("invalid: missing type name")
	} else if c.Zero == "" {
		return errors.New("invalid: missing zero value")
	}
	return nil
}

var (
	configPath = flag.String("config", "", "Path of configuration file (required)")
	outDir     = flag.String("output", "", "Output directory path (required)")

	baseImports = []string{"reflect", "sort", "strings"}
)

func main() {
	flag.Parse()
	switch {
	case *outDir == "":
		log.Fatal("You must specify a non-empty -output directory")
	case *configPath == "":
		log.Fatal("You must specify a non-empty -config path")
	}
	conf, err := readConfig(*configPath)
	if err != nil {
		log.Fatalf("Error loading configuration: %v", err)
	}
	if len(conf.TestValues) > 0 && len(conf.TestValues) != 10 {
		log.Fatalf("Wrong number of test values (%d); exactly 10 are required", len(conf.TestValues))
	}
	if err := os.MkdirAll(*outDir, 0755); err != nil {
		log.Fatalf("Unable to create output directory: %v", err)
	}

	mainT, err := template.New("main").Parse(string(staticfile.MustReadAll("core.go.in")))
	if err != nil {
		log.Fatalf("Invalid main source template: %v", err)
	}
	testT, err := template.New("test").Parse(string(staticfile.MustReadAll("core_test.go.in")))
	if err != nil {
		log.Fatalf("Invalid test source template: %v", err)
	}

	mainPath := filepath.Join(*outDir, conf.Package+".go")
	if err := generate(mainT, conf, mainPath); err != nil {
		log.Fatal(err)
	}
	if len(conf.TestValues) != 0 {
		testPath := filepath.Join(*outDir, conf.Package+"_test.go")
		if err := generate(testT, conf, testPath); err != nil {
			log.Fatal(err)
		}
	}
}

// readConfig loads a configuration from the specified path and reports whether
// it is valid.
func readConfig(path string) (*Config, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var c Config
	if err := toml.Unmarshal(data, &c); err != nil {
		return nil, err
	}

	// Deduplicate the import list, including all those specified by the
	// configuration as well as those needed by the static code.
	imps := make(map[string]bool)
	for _, pkg := range baseImports {
		imps[pkg] = true
	}
	for _, pkg := range c.Imports {
		imps[pkg] = true
	}
	if c.ToString == "" {
		imps["fmt"] = true // for fmt.Sprint
	}
	c.Imports = make([]string, 0, len(imps))
	for pkg := range imps {
		c.Imports = append(c.Imports, pkg)
	}
	sort.Strings(c.Imports)
	return &c, c.validate()
}

// generate renders source text from t using the values in c, formats the
// output as Go source, and writes the result to path.
func generate(t *template.Template, c *Config, path string) error {
	var buf bytes.Buffer
	if err := t.Execute(&buf, c); err != nil {
		return fmt.Errorf("generating source for %q: %v", path, err)
	}
	src, err := format.Source(buf.Bytes())
	if err != nil {
		return fmt.Errorf("formatting source for %q: %v", path, err)
	}
	return ioutil.WriteFile(path, src, 0644)
}
