//go:build ignore

// rr_generate generates zrr.go which houses all the methods that implement the RR interface.

package main

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

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

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

package dns

`

var TypeToRR = template.Must(template.New("TypeToRR").Parse(`
// TypeToRR is a map of constructors for each RR type.
// Basic usage if you have a type  code and want to create a [RR]:
//
//	rr := dns.TypeToRR[dns.TypeMX]()
//	fmt.Println(rr) // "0       CLASS0  MX      0"
var TypeToRR = map[uint16]func() RR{
{{range .}}  Type{{.}}:  func() RR { return new({{.}}) },
{{end}}                    }

`))

var RRToType = template.Must(template.New("RRToType").Parse(`
// RRToType is the reverse of TypeToRR.
func RRToType(rr RR) uint16 {
    switch rr.(type) {
{{range .}}  case *{{.}}:
	return Type{{.}}
{{end}} }
	if x, ok := rr.(Typer); ok {
		return x.Type()
	}
    return TypeNone
}

`))

var TypeToString = template.Must(template.New("typeToString").Parse(`
// TypeToString is a map of strings for each RR type.
// See [codeberg.org/miekg/dns/dnsutil.TypeToString] for a function that works better when the type is unknown.
var TypeToString = map[uint16]string{
{{range .}}{{if (ne . "NSAPPTR")}}  Type{{.}}: "{{.}}",
{{end}}{{end}}                    TypeNSAPPTR:    "NSAP-PTR",
}

`))

var headerFunc = template.Must(template.New("headerFunc").Parse(`
{{range .}}  func (rr *{{.}}) Header() *Header { return &rr.Hdr }
{{end}}

`))

const out = "zrr.go"

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

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

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

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

	generate.Write(source, out)
}
