package dnsmasq

import (
	"cmp"
	"context"
	"io"
	"isle/toolkit"
	"slices"
	"text/template"

	"dev.mediocregopher.com/mediocre-go-lib.git/mlog"
)

// ConfDataHost describes a host which can be resolved by dnsmasq.
type ConfDataHost struct {
	Name string
	IP   string
}

// ConfData describes all the data needed to populate a dnsmasq.conf file.
type ConfData struct {
	Resolvers []string
	Domain    string
	IP        string
	Hosts     []ConfDataHost
}

var confTpl = template.Must(template.New("").Parse(`
port=53

bind-interfaces
listen-address={{ .IP }}

no-resolv
no-hosts

user=
group=

{{- $domain := .Domain -}}

{{- range .Hosts }}
address=/{{ .Name }}.hosts.{{ $domain }}/{{ .IP }}
{{ end -}}

{{- range .Resolvers }}
server={{ . }}
{{ end -}}
`))

// WriteConfFile renders a dnsmasq.conf using the given data to a new
// file at the given path, returning true if the file changed or didn't
// previously exist.
func WriteConfFile(
	ctx context.Context, logger *mlog.Logger, path string, data ConfData,
) (
	bool, error,
) {
	slices.SortFunc(data.Hosts, func(i, j ConfDataHost) int {
		return cmp.Or(
			cmp.Compare(i.IP, j.IP),
			cmp.Compare(i.Name, j.Name),
		)
	})

	return toolkit.WriteFileCheckChanged(
		ctx, logger, path, 0600, func(w io.Writer) error {
			return confTpl.Execute(w, data)
		},
	)
}