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

//go:build ignore

// mkconsts generates const definition files for each GOEXPERIMENT.
package main

import (
	"bytes"
	"fmt"
	"internal/goexperiment"
	"log"
	"os"
	"reflect"
	"strings"
)

func main() {
	// Delete existing experiment constant files.
	ents, err := os.ReadDir(".")
	if err != nil {
		log.Fatal(err)
	}
	for _, ent := range ents {
		name := ent.Name()
		if !strings.HasPrefix(name, "exp_") {
			continue
		}
		// Check that this is definitely a generated file.
		data, err := os.ReadFile(name)
		if err != nil {
			log.Fatalf("reading %s: %v", name, err)
		}
		if !bytes.Contains(data, []byte("Code generated by mkconsts")) {
			log.Fatalf("%s: expected generated file", name)
		}
		if err := os.Remove(name); err != nil {
			log.Fatal(err)
		}
	}

	// Generate new experiment constant files.
	rt := reflect.TypeOf(&goexperiment.Flags{}).Elem()
	for i := 0; i < rt.NumField(); i++ {
		f := rt.Field(i).Name
		buildTag := "goexperiment." + strings.ToLower(f)
		for _, val := range []bool{false, true} {
			name := fmt.Sprintf("exp_%s_%s.go", strings.ToLower(f), pick(val, "off", "on"))
			data := fmt.Sprintf(`// Code generated by mkconsts.go. DO NOT EDIT.

//go:build %s%s

package goexperiment

const %s = %v
const %sInt = %s
`, pick(val, "!", ""), buildTag, f, val, f, pick(val, "0", "1"))
			if err := os.WriteFile(name, []byte(data), 0666); err != nil {
				log.Fatalf("writing %s: %v", name, err)
			}
		}
	}
}

func pick(v bool, f, t string) string {
	if v {
		return t
	}
	return f
}
