use std::{net::SocketAddr, time::Duration};

#[cfg(feature = "https")]
pub mod auto;
pub mod tcp;
#[cfg(feature = "https")]
pub mod tls;

#[cfg(feature = "https")]
pub use auto::AutoConnector;
pub use tcp::TcpConnector;
#[cfg(feature = "https")]
pub use tls::TlsConnector;

pub trait HttpConnection {
    type Error: std::error::Error + Send + 'static;

    fn send(&mut self, buffer: &[u8]) -> Result<usize, Self::Error>;
    fn send_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error>;
    fn recv(&mut self, buffer: &mut [u8]) -> Result<usize, Self::Error>;
    fn recv_exact(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error>;
}

pub trait HttpConnector {
    type Connection: HttpConnection<Error = Self::Error>;
    type Error: std::error::Error + Send + 'static;

    fn default_port(&self, scheme: &str) -> u16;
    fn supports_scheme(&self, scheme: &str) -> bool;
    fn connect(
        &mut self,
        remote: &SocketAddr,
        scheme: &str,
        server_name: &str,
        timeout: Option<Duration>,
        options: HttpConnectionOptions,
    ) -> Result<Self::Connection, Self::Error>;
}

#[derive(Clone)]
pub struct HttpConnectionOptions {
    pub read_timeout: Option<Duration>,
    pub write_timeout: Option<Duration>,
}

impl Default for HttpConnectionOptions {
    fn default() -> Self {
        Self {
            read_timeout: Some(Duration::from_secs(3)),
            write_timeout: Some(Duration::from_secs(3)),
        }
    }
}
