//go:build ignore

package main

import (
	"bytes"
	"flag"
	"html/template"
	"log"
	"slices"

	"codeberg.org/miekg/dns/internal/generate"
)

var hdr = `
// Code generated by "go run ednsrr_generate.go"; DO NOT EDIT.

package dns

`

var CodeToRR = template.Must(template.New("TypeToRR").Parse(`
// CodeToRR is a map of constructors for each EDNS0 RR type.
var CodeToRR = map[uint16]func() EDNS0{
{{range .}}  Code{{.}}:  func() EDNS0 { return new({{.}}) },
{{end}}                    }

`))

var RRToCode = template.Must(template.New("RRToCode").Parse(`
// RRToCode is the reverse of CodeToRR, implemented as a function.
func RRToCode(o EDNS0) uint16 {
    switch o.(type) {
{{range .}}  case *{{.}}:
	return Code{{.}}
{{end}} }
	if x, ok := o.(Typer); ok {
		return x.Type()
	}
    return CodeNone
}

`))

var CodeToString = template.Must(template.New("codeToString").Parse(`
// CodeToString is a map of strings for each EDNS0 RR type.
var CodeToString = map[uint16]string{
{{range .}}  Code{{.}}: "{{.}}",
{{end}}
}

`))

var interfaceFunc = template.Must(template.New("interfaceFunc").Parse(`
	{{range .}}  func (o *{{.}}) Header() *Header { return &Header{Name:"."} }
func (o *{{.}}) Pseudo() bool { return true }
{{end}}

`))

const out = "zednsrr.go"

func main() {
	flag.Parse()
	types, err := generate.Types("edns_types.go")
	if err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	source := &bytes.Buffer{}
	source.WriteString(hdr)
	if err := interfaceFunc.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	types = slices.DeleteFunc(types, func(s string) bool { return s == "ERFC3597" })

	if err := CodeToRR.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}
	if err := RRToCode.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}
	if err := CodeToString.Execute(source, types); err != nil {
		log.Fatalf("Failed to generate %s: %v", out, err)
	}

	generate.Write(source, out)
}
