// Copyright Marcus Del Favero 2025
// Licensed under the GNU AGPLv3 with an exception, see `README.md` for details
#[cfg(feature = "client")] use std::net::SocketAddr;

#[cfg(feature = "client")] use quinn::{Endpoint, Connection};

#[cfg(feature = "client")] use super::{Address, serp::{InitClient, request::Request}, utils::quic::{self, IdleConfig}};

use crate::protocol::{discovery::DiscoveryMessage, info::Info};

#[tokio::main]
pub async fn info(host: &str, port: u16) -> Result<Info, String> {
	let (conn, _security) = quic::connect(quic::client_endpoint()?, host, port, IdleConfig::Default).await?;
	let mut receiver = InitClient::send(conn, Request::Info).await?.main_stream.receiver;
	Ok(receiver.recv().await?)
}

#[cfg(feature = "client")]
pub async fn discover(endpoint: Result<Endpoint, String>, addr: Address) -> Result<DiscoveryMessage, String> {
	let (conn, _security) = quic::connect(endpoint?, &addr.host, addr.port, IdleConfig::Default).await.map_err(|err| format!("cannot connect to server: {err}"))?;
	discover_common(conn).await
}

#[cfg(feature = "client")]
pub async fn discover_with_socket_addr(endpoint: Result<Endpoint, String>, addr: SocketAddr) -> Result<DiscoveryMessage, String> {
	let conn = quic::connect_to_addr(endpoint?, addr, IdleConfig::Default).await.map_err(|err| format!("cannot connect to server: {err}"))?;
	discover_common(conn).await
}

#[cfg(feature = "client")]
async fn discover_common(conn: Connection) -> Result<DiscoveryMessage, String> {
	let mut receiver = InitClient::send(conn, Request::Discover).await?.main_stream.receiver;
	Ok(receiver.recv_with_limit(DiscoveryMessage::SIZE_LIMIT).await?)
}
