// Copyright 2026 The BoringSSL Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::{
    connection::{
        Client,
        Server,
        TlsConnection, //
    },
    context::TlsContext,
    errors::Error,
    io::sync_io::{
        NoAsync,
        StdIoWithReactor, //
    }, //
};

use std::{
    io::{
        Read,
        Write, //
    },
    marker::PhantomData, //
};

/// A convenient wrapper around `TlsContext` for creating synchronous client connections.
pub struct TlsConnector {
    ctx: TlsContext,
}

impl TlsConnector {
    /// Construct a new `TlsConnector`.
    pub(crate) fn new(ctx: TlsContext) -> Self {
        Self { ctx }
    }

    /// Connect to the given domain using the provided stream in one shot.
    ///
    /// This function will drive the handshake until completion.
    ///
    /// This function will **block** on pending I/Os.
    /// For `async` I/O support, use [`TlsConnection::async_handshake`].
    ///
    /// If a non-I/O suspension occurs, including asynchronous certificate verification or a private
    /// key operation, this function returns an error.
    pub fn connect<S>(&self, domain: &str, stream: S) -> Result<TlsStream<Client, S>, Error>
    where
        S: Read + Write + Send + 'static,
    {
        let mut conn = self.ctx.new_client_connection().build();
        #[allow(clippy::expect_used)]
        conn.in_handshake()
            .expect("connection is freshly constructed and it cannot already be established")
            .set_host(domain)?;
        conn.set_io(StdIoWithReactor::new(stream, NoAsync))?;
        if let Some(reason) = conn.do_handshake()? {
            return Err(Error::Unknown(Box::new(reason)));
        }

        Ok(TlsStream {
            conn,
            _marker: PhantomData,
        })
    }
}

/// A wrapper around `TlsContext` for creating synchronous server connections.
pub struct TlsAcceptor {
    ctx: TlsContext,
}

impl TlsAcceptor {
    /// Construct a new `TlsAcceptor`.
    pub(crate) fn new(ctx: TlsContext) -> Self {
        Self { ctx }
    }

    /// Accept a new connection using the provided stream in one shot.
    ///
    /// This function will drive the handshake until completion.
    ///
    /// This function will **block** on pending I/Os.
    /// For `async` I/O support, use [`TlsConnection::async_handshake`].
    ///
    /// If a non-I/O suspension occurs, including asynchronous certificate verification or a private
    /// key operation, this function returns an error.
    pub fn accept<S>(&self, stream: S) -> Result<TlsStream<Server, S>, Error>
    where
        S: Read + Write + Send + 'static,
    {
        let mut conn = self.ctx.new_server_connection().build();
        conn.set_io(StdIoWithReactor::new(stream, NoAsync))?;
        if let Some(reason) = conn.do_handshake()? {
            return Err(Error::Unknown(Box::new(reason)));
        }

        Ok(TlsStream {
            conn,
            _marker: PhantomData,
        })
    }
}

/// A TLS stream driven by synchronous I/O.
pub struct TlsStream<Role, S> {
    conn: TlsConnection<Role>,
    _marker: PhantomData<S>,
}

impl<Role, S> TlsStream<Role, S> {
    /// Get a reference to the underlying `TlsConnection`.
    pub fn get_ref(&self) -> &TlsConnection<Role> {
        &self.conn
    }

    /// Get a mutable reference to the underlying `TlsConnection`.
    pub fn get_mut(&mut self) -> &mut TlsConnection<Role> {
        &mut self.conn
    }
}

impl<Role, S> Read for TlsStream<Role, S> {
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.conn.read(buf)
    }
}

impl<Role, S> Write for TlsStream<Role, S> {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.conn.write(buf)
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Write::flush(&mut self.conn)
    }
}
