package nettool

import (
	"context"
	"crypto/tls"
	"errors"
	"net"
)

// ListenConfigWithOSTCPKeepAlive return a net.ListeConfig with OS-level KeepAlive settings.
func ListenConfigWithOSTCPKeepAlive() *net.ListenConfig {
	return &net.ListenConfig{
		KeepAliveConfig: net.KeepAliveConfig{
			Enable: true,
			// NOTE: Negative values leave the socket-level settings unchanged.
			// Since we don't set them they are inherited from the OS.
			Idle:     -1,
			Interval: -1,
			Count:    -1,
		},
	}
}

func ListenWithOSTCPKeepAlive(ctx context.Context, network, address string) (net.Listener, error) {
	lc := ListenConfigWithOSTCPKeepAlive()
	return lc.Listen(ctx, network, address)
}

func TLSListenWithOSTCPKeepAlive(ctx context.Context, network, address string, config *tls.Config) (net.Listener, error) {
	if config == nil || len(config.Certificates) == 0 &&
		config.GetCertificate == nil && config.GetConfigForClient == nil {
		return nil, errors.New("tls: neither Certificates, GetCertificate, nor GetConfigForClient set in Config")
	}
	l, err := ListenWithOSTCPKeepAlive(ctx, network, address)
	if err != nil {
		return nil, err
	}
	return tls.NewListener(l, config), nil
}
