/*-
 * Scram-rs - a SCRAM authentification authorization library
 * 
 * Copyright (C) 2021  Aleksandr Morozov
 * Copyright (C) 2025 Aleksandr Morozov
 * 
 * The syslog-rs crate can be redistributed and/or modified
 * under the terms of either of the following licenses:
 *
 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
 *
 *   2. The MIT License (MIT)
 *                     
 *   3. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
 */

 
#[cfg(feature = "std")]
use std::fmt;

#[cfg(not(feature = "std"))]
use core::fmt;

#[cfg(not(feature = "std"))]
use alloc::boxed::Box;


use async_trait::async_trait;

use crate::{ScramHashing, ScramKey, ScramPassword, ScramResult};


/// A authentification backend which is behind the SCRAM lib.
/// A program which uses this crate should implement this trait to its auth
/// instance.
/// 
/// # Examples
/// 
/// ```ignore
/// #[derive(Debug)]
/// struct AuthServer
/// {
///     password: String,   
/// }
/// 
/// impl AuthServer
/// {
///       fn lookup(&self, username: &str) -> Option<String>
///         { return Some(self.password.clone());}
/// }
///
/// #[async_trait]
/// impl AsyncScramAuthServer<ScramSha256RustNative> for AuthServer
/// {
///     async fn get_password_for_user(&self, username: &str, _authzid: Option<&str>) -> ScramResult<ScramPassword>
///     {
///         let password = match self.lookup(username)
///         {
///             Some(r) => ScramPassword::found_plaintext_password::<ScramSha256RustNative>(r.as_bytes(), None),
///             None => ScramPassword::not_found::<ScramSha256RustNative>()
///         };
/// 
///         return password;
/// 
///     }
/// }
/// ```
#[async_trait]
pub trait AsyncScramAuthServer<S: ScramHashing>: fmt::Debug
{
    /// A crate makes request to the upstream code to retrive the `password` for the `username`.
    /// 
    /// # Arguments
    /// 
    /// `username` - a reference to the UTF-8 valid username string which was requested to auth.
    /// 
    /// `authzid` - an optional value and may not present if it was not included.
    async fn get_password_for_user(&self, username: &str, authzid: Option<&str>) -> ScramResult<ScramPassword>;
}

/// A authentification backend which is behind the SCRAM lib.
/// A program which uses this crate should implement this trait to its auth
/// instance.
/// 
/// # Examples
/// 
/// ```ignore
/// use async_trait::async_trait; 
/// #[async_trait]
/// impl AsyncScramAuthClient for <ProgramStruct>
/// {
///     async fn get_username(&self) -> &str
///     {
///         return &self.username;
///     }
/// 
///     async fn get_password(&self) -> &str
///     {
///         return &self.password;
///     }
/// }
/// ```
#[async_trait]
pub trait AsyncScramAuthClient: fmt::Debug
{
    /// This function must return plain text username.
    async fn get_username(&self) -> &str;

    /// This function must return plain text password.
    async fn get_password(&self) -> &str;

    /// This function may return the authzid a= (UTF-8) if any.
    async fn get_authzid(&self) -> Option<&str>
    {
        return None;
    }

    /// This function returns a custom [ScramKey] instance if any other
    /// keys are used. If returns [Option::None] the default will be used.
    async fn get_scram_keys(&self) -> Option<&ScramKey>
    {
        return None;
    }
}
