use std::{error::Error, sync::Arc};

use tokio::net::TcpListener;

use crate::ServerState;

pub async fn listen(state: Arc<ServerState>) -> Result<(), Box<dyn Error>> {
    let bind_addr = &state.config.tcp_listen_addr;

    let listener = TcpListener::bind(bind_addr).await?;
    tracing::info!("listening at {bind_addr}");

    loop {
        let Ok((stream, addr)) = listener.accept().await else {
            continue;
        };

        tracing::info!("new connection from {addr}");
        let session = state.session_mgr.create(stream);

        let state = state.clone();
        tokio::spawn(async move {
            match session.run(state).await {
                Ok(()) => tracing::info!("session from {addr} disconnected"),
                Err(err) => {
                    tracing::error!("error occurred: {err}, session from {addr} disconnected!");
                }
            }
        });
    }
}
