use std::collections::VecDeque;

use tokio::sync::Mutex;
use zeromq::{PullSocket, Socket, SocketRecv};

use crate::config::IpString;

use super::{tools::Packet, NetError, NetResult};

mod aserver_session;
pub use aserver_session::AServerSession;

pub struct AServer(Mutex<PullSocket>);

impl AServer {
    pub async fn bind(host: IpString) -> NetResult<Self> {
        let mut socket = PullSocket::new();
        socket
            .bind(&format!("tcp://{}", host.0))
            .await
            .map_err(|err| NetError::BindFail(err))?;

        Ok(Self(Mutex::new(socket)))
    }

    pub async fn recv(&self) -> NetResult<VecDeque<Packet>> {
        let message = self
            .0
            .lock()
            .await
            .recv()
            .await
            .map_err(|err| NetError::RecvFail(err))?;

        let out = message
            .into_vecdeque()
            .into_iter()
            .map(|buf| match Packet::parse_from_array(&buf) {
                Ok(packet) => Some(packet),
                Err(err) => {
                    tracing::warn!("Failed to parse packet: {err}");
                    None
                }
            })
            .flatten()
            .collect();

        Ok(out)
    }
}
