//go:build ignore

package main

import (
	"bytes"
	"go/format"
	"log"
	"os"
	"text/template"
)

type Option struct {
	Name        string
	Flag        string
	Type        string
	Description string
}

var data = []Option{
	{Name: "CompactOutput", Flag: "c", Type: "bool", Description: "Compact output"},
	{Name: "NullInput", Flag: "n", Type: "bool", Description: "Use null input"},
	{Name: "Slurp", Flag: "s", Type: "bool", Description: "Slurp input"},
	{Name: "RawOutput", Flag: "r", Type: "bool", Description: "Raw output"},
	{Name: "JoinOutput", Flag: "j", Type: "bool", Description: "Join output"},
	{Name: "ASCIIOutput", Flag: "a", Type: "bool", Description: "ASCII output"},
	{Name: "RawInput", Flag: "R", Type: "bool", Description: "Read raw strings"},
	{Name: "Monochrome", Flag: "M", Type: "bool", Description: "Monochrome output"},
	{Name: "ForceColor", Flag: "C", Type: "bool", Description: "Force color"},
	{Name: "SortKeys", Flag: "S", Type: "bool", Description: "Sort keys"},
	{Name: "LibraryPaths", Flag: "L", Type: "[]string", Description: "Add path to library search path"},
	{Name: "HideInputPane", Flag: "hide-input-pane", Type: "bool", Description: "Hide input (left) viewing pane"},
	{Name: "JQCommand", Flag: "jqbin", Type: "string", Description: "name of or path to jq binary to use"},
	{Name: "HistoryFile", Flag: "H", Type: "string", Description: "set path to history file. Set to '' to disable history"},
}

const generatedTemplate = `// Code generated by go generate; DO NOT EDIT.

package options

import "encoding"

var (
{{- range . }}
	_ Option = (*{{ .Name }})(nil)
	_ encoding.TextUnmarshaler = (*{{ .Name }})(nil)
{{- end }}
)

type (
{{- range . }}
	{{ .Name }} {{ .Type }}
{{- end }}
)

type Options struct {
{{- range . }}
	{{ .Name }} {{ .Name }}
{{- end }}
}

{{ range . }}
func ({{ .Name }}) String() string {
	return {{ printf "%q" .Description }}
}

func ({{ .Name }}) Flag() string {
	return {{ printf "%q" .Flag }}
}

{{- if eq .Type "bool" }}
func (option *{{ .Name }}) Set(value string) error {
	return setBoolOption(option, value)
}

func (option *{{ .Name }}) IsBoolFlag() bool {
	return true
}

{{- else if eq .Type "string" }}
func (option *{{ .Name }}) Set(value string) error {
	*option = {{ .Name }}(value)
	return nil
}

{{- else if eq .Type "[]string" }}
func (option *{{ .Name }}) Set(value string) error {
	*option = append(*option, value)
	return nil
}
{{- end }}

func (option *{{ .Name }}) UnmarshalText(text []byte) error {
	return unmarshalTextValue(option, text)
}

{{ end -}}
`

func main() {
	tmpl, err := template.New("options").Parse(generatedTemplate)
	if err != nil {
		log.Fatal(err)
	}

	var buffer bytes.Buffer
	if err := tmpl.Execute(&buffer, data); err != nil {
		log.Fatal(err)
	}

	source, err := format.Source(buffer.Bytes())
	if err != nil {
		log.Fatalf("format generated source: %v\n%s", err, buffer.Bytes())
	}

	if err := os.WriteFile("options_gen.go", source, 0o644); err != nil {
		log.Fatal(err)
	}
}
