use crate::client::identity::{Identity, IdentityFuture, ResolveIdentity};
use crate::client::runtime_components::RuntimeComponents;
use aws_smithy_types::config_bag::ConfigBag;
use std::fmt::Debug;
use std::sync::Arc;
use std::time::SystemTime;
use zeroize::Zeroizing;
#[derive(Clone, Eq, PartialEq)]
pub struct Token(Arc<TokenInner>);
#[derive(Eq, PartialEq)]
struct TokenInner {
    token: Zeroizing<String>,
    expiration: Option<SystemTime>,
}
impl Debug for Token {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Token")
            .field("token", &"** redacted **")
            .finish()
    }
}
impl Token {
    pub fn new(token: impl Into<String>, expiration: Option<SystemTime>) -> Self {
        Self(Arc::new(TokenInner {
            token: Zeroizing::new(token.into()),
            expiration,
        }))
    }
    pub fn token(&self) -> &str {
        &self.0.token
    }
    pub fn expiration(&self) -> Option<SystemTime> {
        self.0.expiration
    }
    #[cfg(feature = "test-util")]
    pub fn for_tests() -> Self {
        Self::new("test-token", None)
    }
}
impl From<&str> for Token {
    fn from(token: &str) -> Self {
        Self::from(token.to_owned())
    }
}
impl From<String> for Token {
    fn from(api_key: String) -> Self {
        Self(Arc::new(TokenInner {
            token: Zeroizing::new(api_key),
            expiration: None,
        }))
    }
}
impl ResolveIdentity for Token {
    fn resolve_identity<'a>(
        &'a self,
        _runtime_components: &'a RuntimeComponents,
        _config_bag: &'a ConfigBag,
    ) -> IdentityFuture<'a> {
        IdentityFuture::ready(Ok(self.into()))
    }
}
impl From<&Token> for Identity {
    fn from(value: &Token) -> Self {
        Identity::new(value.clone(), value.0.expiration)
    }
}
impl From<Token> for Identity {
    fn from(value: Token) -> Self {
        let expiration = value.0.expiration;
        Identity::new(value, expiration)
    }
}
#[derive(Clone, Eq, PartialEq)]
pub struct Login(Arc<LoginInner>);
#[derive(Eq, PartialEq)]
struct LoginInner {
    user: String,
    password: Zeroizing<String>,
    expiration: Option<SystemTime>,
}
impl Debug for Login {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Login")
            .field("user", &self.0.user)
            .field("password", &"** redacted **")
            .finish()
    }
}
impl Login {
    pub fn new(
        user: impl Into<String>,
        password: impl Into<String>,
        expiration: Option<SystemTime>,
    ) -> Self {
        Self(Arc::new(LoginInner {
            user: user.into(),
            password: Zeroizing::new(password.into()),
            expiration,
        }))
    }
    pub fn user(&self) -> &str {
        &self.0.user
    }
    pub fn password(&self) -> &str {
        &self.0.password
    }
    pub fn expiration(&self) -> Option<SystemTime> {
        self.0.expiration
    }
}
impl ResolveIdentity for Login {
    fn resolve_identity<'a>(
        &'a self,
        _runtime_components: &'a RuntimeComponents,
        _config_bag: &'a ConfigBag,
    ) -> IdentityFuture<'a> {
        IdentityFuture::ready(Ok(Identity::new(self.clone(), self.0.expiration)))
    }
}