package networking

import (
	"crypto/tls"
	"fmt"
	"log"
	"net"
)

type ServerTLSConfigProvider interface {
	GetServerTLSConfig() *tls.Config
}

type Server[T any] struct {
	listener net.Listener
	C        chan Connection[T]
}

func NewServer[T any](serverTLSConfigProvider ServerTLSConfigProvider, port int) Server[T] {

	listener, err := tls.Listen("tcp", fmt.Sprintf("0.0.0.0:%d", port), serverTLSConfigProvider.GetServerTLSConfig())
	if err != nil {
		panic("Server could not bind to address")
	}
	return Server[T]{
		listener: listener,
		C:        make(chan Connection[T]),
	}
}

func (s *Server[T]) ListenLoop() {

	for {
		listenerConn, err := s.listener.Accept()
		if err != nil {
			panic("Server could not accept connection")
		}
		tlsConn, ok := listenerConn.(*tls.Conn)
		if !ok {
			panic("Connection is not a TLS connection")
		}
        tlsConn.Handshake()

		state := tlsConn.ConnectionState()
		if len(state.PeerCertificates) == 0 {
			log.Panicln("Client did not provide a certificate")
		}
		conn := NewConnection[T](tlsConn)
		s.C <- conn
	}
}