package network

import (
	"crypto/tls"
	"git.hpds.cc/Component/network/log"
	"github.com/quic-go/quic-go"
	"net"
	"time"

	pkgtls "git.hpds.cc/Component/network/tls"
)

// A Listener for incoming connections
type Listener interface {
	quic.Listener
	// Name Listener's name
	Name() string
	// Versions get Version
	Versions() []string
}

var _ Listener = (*defaultListener)(nil)

type defaultListener struct {
	conf *quic.Config
	quic.Listener
}

// DefaultQuicConfig be used when `quicConfig` is nil.
var DefaultQuicConfig = &quic.Config{
	Versions:                       []quic.VersionNumber{quic.Version1, quic.VersionDraft29},
	MaxIdleTimeout:                 time.Second * 5,
	KeepAlivePeriod:                time.Second * 2,
	MaxIncomingStreams:             1000,
	MaxIncomingUniStreams:          1000,
	HandshakeIdleTimeout:           time.Second * 3,
	InitialStreamReceiveWindow:     1024 * 1024 * 2,
	InitialConnectionReceiveWindow: 1024 * 1024 * 2,
	// DisablePathMTUDiscovery:        true,
}

func newListener(conn net.PacketConn, tlsConfig *tls.Config, quicConfig *quic.Config) (*defaultListener, error) {
	if tlsConfig == nil {
		tc, err := pkgtls.CreateServerTLSConfig(conn.LocalAddr().String())
		if err != nil {
			log.Errorf("CreateServerTLSConfig: %v", err)
			return &defaultListener{}, err
		}
		tlsConfig = tc
	}

	if quicConfig == nil {
		quicConfig = DefaultQuicConfig
	}

	quicListener, err := quic.Listen(conn, tlsConfig, quicConfig)
	if err != nil {
		log.Errorf("quic Listen: %v", err)
		return &defaultListener{}, err
	}

	return &defaultListener{conf: quicConfig, Listener: quicListener}, nil
}

func (l *defaultListener) Name() string { return "QUIC-Server" }

func (l *defaultListener) Versions() []string {
	versions := make([]string, len(l.conf.Versions))
	for k, v := range l.conf.Versions {
		versions[k] = v.String()
	}
	return versions
}