use crate::metadata::{MetadataMap, MetadataValue};
#[cfg(feature = "transport")]
use crate::transport::server::TcpConnectInfo;
#[cfg(feature = "tls")]
use crate::transport::{server::TlsConnectInfo, Certificate};
use crate::Extensions;
#[cfg(feature = "transport")]
use std::net::SocketAddr;
#[cfg(feature = "tls")]
use std::sync::Arc;
use std::time::Duration;
use tokio_stream::Stream;

/// A gRPC request and metadata from an RPC call.
#[derive(Debug)]
pub struct Request<T> {
    metadata: MetadataMap,
    message: T,
    extensions: Extensions,
}

/// Trait implemented by RPC request types.
///
/// Types implementing this trait can be used as arguments to client RPC
/// methods without explicitly wrapping them into `tonic::Request`s. The purpose
/// is to make client calls slightly more convenient to write.
///
/// Tonic's code generation and blanket implementations handle this for you,
/// so it is not necessary to implement this trait directly.
///
/// # Example
///
/// Given the following gRPC method definition:
/// ```proto
/// rpc GetFeature(Point) returns (Feature) {}
/// ```
///
/// we can call `get_feature` in two equivalent ways:
/// ```rust
/// # pub struct Point {}
/// # pub struct Client {}
/// # impl Client {
/// #   fn get_feature(&self, r: impl tonic::IntoRequest<Point>) {}
/// # }
/// # let client = Client {};
/// use tonic::Request;
///
/// client.get_feature(Point {});
/// client.get_feature(Request::new(Point {}));
/// ```
pub trait IntoRequest<T>: sealed::Sealed {
    /// Wrap the input message `T` in a `tonic::Request`
    fn into_request(self) -> Request<T>;
}

/// Trait implemented by RPC streaming request types.
///
/// Types implementing this trait can be used as arguments to client streaming
/// RPC methods without explicitly wrapping them into `tonic::Request`s. The
/// purpose is to make client calls slightly more convenient to write.
///
/// Tonic's code generation and blanket implementations handle this for you,
/// so it is not necessary to implement this trait directly.
///
/// # Example
///
/// Given the following gRPC service method definition:
/// ```proto
/// rpc RecordRoute(stream Point) returns (RouteSummary) {}
/// ```
/// we can call `record_route` in two equivalent ways:
///
/// ```rust
/// # #[derive(Clone)]
/// # pub struct Point {};
/// # pub struct Client {};
/// # impl Client {
/// #   fn record_route(&self, r: impl tonic::IntoStreamingRequest<Message = Point>) {}
/// # }
/// # let client = Client {};
/// use tonic::Request;
///
/// let messages = vec![Point {}, Point {}];
///
/// client.record_route(Request::new(tokio_stream::iter(messages.clone())));
/// client.record_route(tokio_stream::iter(messages));
/// ```
pub trait IntoStreamingRequest: sealed::Sealed {
    /// The RPC request stream type
    type Stream: Stream<Item = Self::Message> + Send + 'static;

    /// The RPC request type
    type Message;

    /// Wrap the stream of messages in a `tonic::Request`
    fn into_streaming_request(self) -> Request<Self::Stream>;
}

impl<T> Request<T> {
    /// Create a new gRPC request.
    ///
    /// ```rust
    /// # use tonic::Request;
    /// # pub struct HelloRequest {
    /// #   pub name: String,
    /// # }
    /// Request::new(HelloRequest {
    ///    name: "Bob".into(),
    /// });
    /// ```
    pub fn new(message: T) -> Self {
        Request {
            metadata: MetadataMap::new(),
            message,
            extensions: Extensions::new(),
        }
    }

    /// Get a reference to the message
    pub fn get_ref(&self) -> &T {
        &self.message
    }

    /// Get a mutable reference to the message
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.message
    }

    /// Get a reference to the custom request metadata.
    pub fn metadata(&self) -> &MetadataMap {
        &self.metadata
    }

    /// Get a mutable reference to the request metadata.
    pub fn metadata_mut(&mut self) -> &mut MetadataMap {
        &mut self.metadata
    }

    /// Consumes `self`, returning the message
    pub fn into_inner(self) -> T {
        self.message
    }

    /// Consumes `self` returning the parts of the request.
    pub fn into_parts(self) -> (MetadataMap, Extensions, T) {
        (self.metadata, self.extensions, self.message)
    }

    /// Create a new gRPC request from metadata, extensions and message.
    pub fn from_parts(metadata: MetadataMap, extensions: Extensions, message: T) -> Self {
        Self {
            metadata,
            extensions,
            message,
        }
    }

    pub(crate) fn from_http_parts(parts: http::request::Parts, message: T) -> Self {
        Request {
            metadata: MetadataMap::from_headers(parts.headers),
            message,
            extensions: Extensions::from_http(parts.extensions),
        }
    }

    /// Convert an HTTP request to a gRPC request
    pub fn from_http(http: http::Request<T>) -> Self {
        let (parts, message) = http.into_parts();
        Request::from_http_parts(parts, message)
    }

    pub(crate) fn into_http(
        self,
        uri: http::Uri,
        method: http::Method,
        version: http::Version,
        sanitize_headers: SanitizeHeaders,
    ) -> http::Request<T> {
        let mut request = http::Request::new(self.message);

        *request.version_mut() = version;
        *request.method_mut() = method;
        *request.uri_mut() = uri;
        *request.headers_mut() = match sanitize_headers {
            SanitizeHeaders::Yes => self.metadata.into_sanitized_headers(),
            SanitizeHeaders::No => self.metadata.into_headers(),
        };
        *request.extensions_mut() = self.extensions.into_http();

        request
    }

    #[doc(hidden)]
    pub fn map<F, U>(self, f: F) -> Request<U>
    where
        F: FnOnce(T) -> U,
    {
        let message = f(self.message);

        Request {
            metadata: self.metadata,
            message,
            extensions: self.extensions,
        }
    }

    /// Get the local address of this connection.
    ///
    /// This will return `None` if the `IO` type used
    /// does not implement `Connected` or when using a unix domain socket.
    /// This currently only works on the server side.
    #[cfg(feature = "transport")]
    #[cfg_attr(docsrs, doc(cfg(feature = "transport")))]
    pub fn local_addr(&self) -> Option<SocketAddr> {
        let addr = self
            .extensions()
            .get::<TcpConnectInfo>()
            .and_then(|i| i.local_addr());

        #[cfg(feature = "tls")]
        let addr = addr.or_else(|| {
            self.extensions()
                .get::<TlsConnectInfo<TcpConnectInfo>>()
                .and_then(|i| i.get_ref().local_addr())
        });

        addr
    }

    /// Get the remote address of this connection.
    ///
    /// This will return `None` if the `IO` type used
    /// does not implement `Connected` or when using a unix domain socket.
    /// This currently only works on the server side.
    #[cfg(feature = "transport")]
    #[cfg_attr(docsrs, doc(cfg(feature = "transport")))]
    pub fn remote_addr(&self) -> Option<SocketAddr> {
        let addr = self
            .extensions()
            .get::<TcpConnectInfo>()
            .and_then(|i| i.remote_addr());

        #[cfg(feature = "tls")]
        let addr = addr.or_else(|| {
            self.extensions()
                .get::<TlsConnectInfo<TcpConnectInfo>>()
                .and_then(|i| i.get_ref().remote_addr())
        });

        addr
    }

    /// Get the peer certificates of the connected client.
    ///
    /// This is used to fetch the certificates from the TLS session
    /// and is mostly used for mTLS. This currently only returns
    /// `Some` on the server side of the `transport` server with
    /// TLS enabled connections.
    #[cfg(feature = "tls")]
    #[cfg_attr(docsrs, doc(cfg(feature = "tls")))]
    pub fn peer_certs(&self) -> Option<Arc<Vec<Certificate>>> {
        self.extensions()
            .get::<TlsConnectInfo<TcpConnectInfo>>()
            .and_then(|i| i.peer_certs())
    }

    /// Set the max duration the request is allowed to take.
    ///
    /// Requires the server to support the `grpc-timeout` metadata, which Tonic does.
    ///
    /// The duration will be formatted according to [the spec] and use the most precise unit
    /// possible.
    ///
    /// Example:
    ///
    /// ```rust
    /// use std::time::Duration;
    /// use tonic::Request;
    ///
    /// let mut request = Request::new(());
    ///
    /// request.set_timeout(Duration::from_secs(30));
    ///
    /// let value = request.metadata().get("grpc-timeout").unwrap();
    ///
    /// assert_eq!(
    ///     value,
    ///     // equivalent to 30 seconds
    ///     "30000000u"
    /// );
    /// ```
    ///
    /// [the spec]: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
    pub fn set_timeout(&mut self, deadline: Duration) {
        let value: MetadataValue<_> = duration_to_grpc_timeout(deadline).parse().unwrap();
        self.metadata_mut()
            .insert(crate::metadata::GRPC_TIMEOUT_HEADER, value);
    }

    /// Returns a reference to the associated extensions.
    pub fn extensions(&self) -> &Extensions {
        &self.extensions
    }

    /// Returns a mutable reference to the associated extensions.
    ///
    /// # Example
    ///
    /// Extensions can be set in interceptors:
    ///
    /// ```no_run
    /// use tonic::{Request, service::interceptor};
    ///
    /// struct MyExtension {
    ///     some_piece_of_data: String,
    /// }
    ///
    /// interceptor(|mut request: Request<()>| {
    ///     request.extensions_mut().insert(MyExtension {
    ///         some_piece_of_data: "foo".to_string(),
    ///     });
    ///
    ///     Ok(request)
    /// });
    /// ```
    ///
    /// And picked up by RPCs:
    ///
    /// ```no_run
    /// use tonic::{async_trait, Status, Request, Response};
    /// #
    /// # struct Output {}
    /// # struct Input;
    /// # struct MyService;
    /// # struct MyExtension;
    /// # #[async_trait]
    /// # trait TestService {
    /// #     async fn handler(&self, req: Request<Input>) -> Result<Response<Output>, Status>;
    /// # }
    ///
    /// #[async_trait]
    /// impl TestService for MyService {
    ///     async fn handler(&self, req: Request<Input>) -> Result<Response<Output>, Status> {
    ///         let value: &MyExtension = req.extensions().get::<MyExtension>().unwrap();
    ///
    ///         Ok(Response::new(Output {}))
    ///     }
    /// }
    /// ```
    pub fn extensions_mut(&mut self) -> &mut Extensions {
        &mut self.extensions
    }
}

impl<T> IntoRequest<T> for T {
    fn into_request(self) -> Request<Self> {
        Request::new(self)
    }
}

impl<T> IntoRequest<T> for Request<T> {
    fn into_request(self) -> Request<T> {
        self
    }
}

impl<T> IntoStreamingRequest for T
where
    T: Stream + Send + 'static,
{
    type Stream = T;
    type Message = T::Item;

    fn into_streaming_request(self) -> Request<Self> {
        Request::new(self)
    }
}

impl<T> IntoStreamingRequest for Request<T>
where
    T: Stream + Send + 'static,
{
    type Stream = T;
    type Message = T::Item;

    fn into_streaming_request(self) -> Self {
        self
    }
}

impl<T> sealed::Sealed for T {}

mod sealed {
    pub trait Sealed {}
}

fn duration_to_grpc_timeout(duration: Duration) -> String {
    fn try_format<T: Into<u128>>(
        duration: Duration,
        unit: char,
        convert: impl FnOnce(Duration) -> T,
    ) -> Option<String> {
        // The gRPC spec specifies that the timeout most be at most 8 digits. So this is the largest a
        // value can be before we need to use a bigger unit.
        let max_size: u128 = 99_999_999; // exactly 8 digits

        let value = convert(duration).into();
        if value > max_size {
            None
        } else {
            Some(format!("{}{}", value, unit))
        }
    }

    // pick the most precise unit that is less than or equal to 8 digits as per the gRPC spec
    try_format(duration, 'n', |d| d.as_nanos())
        .or_else(|| try_format(duration, 'u', |d| d.as_micros()))
        .or_else(|| try_format(duration, 'm', |d| d.as_millis()))
        .or_else(|| try_format(duration, 'S', |d| d.as_secs()))
        .or_else(|| try_format(duration, 'M', |d| d.as_secs() / 60))
        .or_else(|| {
            try_format(duration, 'H', |d| {
                let minutes = d.as_secs() / 60;
                minutes / 60
            })
        })
        // duration has to be more than 11_415 years for this to happen
        .expect("duration is unrealistically large")
}

/// When converting a `tonic::Request` into a `http::Request` should reserved
/// headers be removed?
pub(crate) enum SanitizeHeaders {
    Yes,
    No,
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::metadata::MetadataValue;
    use http::Uri;

    #[test]
    fn reserved_headers_are_excluded() {
        let mut r = Request::new(1);

        for header in &MetadataMap::GRPC_RESERVED_HEADERS {
            r.metadata_mut()
                .insert(*header, MetadataValue::from_static("invalid"));
        }

        let http_request = r.into_http(
            Uri::default(),
            http::Method::POST,
            http::Version::HTTP_2,
            SanitizeHeaders::Yes,
        );
        assert!(http_request.headers().is_empty());
    }

    #[test]
    fn duration_to_grpc_timeout_less_than_second() {
        let timeout = Duration::from_millis(500);
        let value = duration_to_grpc_timeout(timeout);
        assert_eq!(value, format!("{}u", timeout.as_micros()));
    }

    #[test]
    fn duration_to_grpc_timeout_more_than_second() {
        let timeout = Duration::from_secs(30);
        let value = duration_to_grpc_timeout(timeout);
        assert_eq!(value, format!("{}u", timeout.as_micros()));
    }

    #[test]
    fn duration_to_grpc_timeout_a_very_long_time() {
        let one_hour = Duration::from_secs(60 * 60);
        let value = duration_to_grpc_timeout(one_hour);
        assert_eq!(value, format!("{}m", one_hour.as_millis()));
    }
}
