// Code generated by software.amazon.smithy.rust.codegen.smithy-rs. DO NOT EDIT.
pub use ::aws_smithy_http::operation::Operation;
pub use ::aws_smithy_http::operation::Request;
pub use ::aws_smithy_http::operation::Response;
pub use ::aws_smithy_http::retry::ClassifyRetry;
pub use ::aws_smithy_types::retry::RetryKind;
/// A wrapper type for [`Operation`](aws_smithy_http::operation::Operation)s that allows for
/// customization of the operation before it is sent. A `CustomizableOperation` may be sent
/// by calling its [`.send()`][crate::client::customize::CustomizableOperation::send] method.
#[derive(Debug)]
pub struct CustomizableOperation<O, Retry> {
    pub(crate) handle: ::std::sync::Arc<crate::client::Handle>,
    pub(crate) operation: Operation<O, Retry>,
}

impl<O, Retry> CustomizableOperation<O, Retry> {
    /// Allows for customizing the operation's request
    pub fn map_request<E>(
        mut self,
        f: impl ::std::ops::FnOnce(
            ::http::Request<::aws_smithy_http::body::SdkBody>,
        ) -> ::std::result::Result<
            ::http::Request<::aws_smithy_http::body::SdkBody>,
            E,
        >,
    ) -> ::std::result::Result<Self, E> {
        let (request, response) = self.operation.into_request_response();
        let request = request.augment(|req, _props| f(req))?;
        self.operation = Operation::from_parts(request, response);
        ::std::result::Result::Ok(self)
    }

    /// Convenience for `map_request` where infallible direct mutation of request is acceptable
    pub fn mutate_request(
        self,
        f: impl ::std::ops::FnOnce(&mut ::http::Request<::aws_smithy_http::body::SdkBody>),
    ) -> Self {
        self.map_request(|mut req| {
            f(&mut req);
            ::std::result::Result::<_, ::std::convert::Infallible>::Ok(req)
        })
        .expect("infallible")
    }

    /// Allows for customizing the entire operation
    pub fn map_operation<E>(
        mut self,
        f: impl ::std::ops::FnOnce(Operation<O, Retry>) -> ::std::result::Result<Operation<O, Retry>, E>,
    ) -> ::std::result::Result<Self, E> {
        self.operation = f(self.operation)?;
        ::std::result::Result::Ok(self)
    }

    /// Direct access to read the HTTP request
    pub fn request(&self) -> &::http::Request<::aws_smithy_http::body::SdkBody> {
        self.operation.request()
    }

    /// Direct access to mutate the HTTP request
    pub fn request_mut(&mut self) -> &mut ::http::Request<::aws_smithy_http::body::SdkBody> {
        self.operation.request_mut()
    }

    #[doc(hidden)]
    // This is a temporary method for testing. NEVER use it in production
    pub fn request_time_for_tests(mut self, request_time: ::std::time::SystemTime) -> Self {
        self.operation.properties_mut().insert(request_time);
        self
    }

    #[doc(hidden)]
    // This is a temporary method for testing. NEVER use it in production
    pub fn user_agent_for_tests(mut self) -> Self {
        self.operation
            .properties_mut()
            .insert(::aws_http::user_agent::AwsUserAgent::for_tests());
        self
    }
}

impl<O, Retry> CustomizableOperation<O, Retry> {
    /// Sends this operation's request
    pub async fn send<T, E>(
        self,
    ) -> ::std::result::Result<T, ::aws_smithy_http::result::SdkError<E>>
    where
        E: std::error::Error + ::std::marker::Send + ::std::marker::Sync + 'static,
        O: ::aws_smithy_http::response::ParseHttpResponse<Output = ::std::result::Result<T, E>>
            + ::std::marker::Send
            + ::std::marker::Sync
            + ::std::clone::Clone
            + 'static,
        Retry: ::aws_smithy_http::retry::ClassifyRetry<
                ::aws_smithy_http::result::SdkSuccess<T>,
                ::aws_smithy_http::result::SdkError<E>,
            > + ::std::marker::Send
            + ::std::marker::Sync
            + ::std::clone::Clone,
    {
        self.handle.client.call(self.operation).await
    }
}
