package internal

import (
	"context"
	"time"

	"github.com/miekg/dns"
)

type DNSServer struct {
	srv *dns.Server
	dns.Handler
}

func (d *DNSServer) ListenAndServe(ctx context.Context, addr string) error {
	errs := make(chan error)

	c, canceller := context.WithCancel(ctx)
	go d.runServer(c, "udp", addr, errs)
	go d.runServer(c, "tcp", addr, errs)

	defer canceller()
	select {
	case <-ctx.Done():
		return nil
	case err := <-errs:
		return err
	}
}

func (d *DNSServer) runServer(ctx context.Context, net, addr string, in chan<- error) {
	d.srv = &dns.Server{
		Addr:        addr,
		Net:         net,
		IdleTimeout: func() time.Duration { return time.Second * 5 },
		Handler:     d,
	}

	go func() {
		<-ctx.Done()
		d.srv.Listener.Close()
	}()

	if err := d.srv.ListenAndServe(); err != nil {
		in <- err
	}
}
