#[cfg(doc)]
use crate::KeyHandle;

/// How the password is obtained.
#[derive(Debug)]
pub enum PasswordSource {
    // keystore_protocol.capnp PasswordSource:

    /// The application must provide the password to unlock the key.
    ///
    /// This means that if a key is locked, then before executing a
    /// private key operation, the key must be unlocked using
    /// [`KeyHandle::unlock`].
    Inline,

    /// The application must provide the password to unlock the key,
    /// but operations must be confirmed externally.
    ///
    /// This means that if a key is locked, then before executing a
    /// private key operation, the key must be unlocked using
    /// [`KeyHandle::unlock`].  These operations may require the user
    /// externally confirm the operation.
    InlineWithConfirmation,

    /// The user must provide the password out of band.
    ///
    /// The user provides the password using an external pinpad, or
    /// via a trusted user interface so as to not reveal the password
    /// to the application or system.
    ///
    /// This means if the key is locked, the user will be prompted to
    /// unlock it as a side effect of a private key operation.
    ///
    /// The application can use [`KeyHandle::unlock`] to proactively
    /// cause the user to be prompted to unlock the key.
    ExternalOnDemand,

    /// The user must provide the password out of band as a side
    /// effect of an operation.
    ///
    /// The user provides the password using an external pinpad, or
    /// via a trusted user interface so as to not reveal the password
    /// to the application or system.
    ///
    /// This means if the key is locked, the user will be prompted to
    /// unlock it as a side effect of a private key operation.
    ///
    /// The application cannot proactively cause the user to be
    /// prompted to unlock the key; the prompt is only a side effect
    /// of a private key operation.  That is, the key cannot be
    /// unlocked using [`KeyHandle::unlock`].
    ExternalSideEffect,
}

impl PasswordSource {
    /// Returns whether the password needs to be provided inline.
    ///
    /// Returns whether this is [`PasswordSource::Inline`] or
    /// [`PasswordSource::InlineWithConfirmation`].
    pub fn is_inline(&self) -> bool {
        match self {
            PasswordSource::Inline => true,
            PasswordSource::InlineWithConfirmation => true,
            PasswordSource::ExternalSideEffect => false,
            PasswordSource::ExternalOnDemand => false,
        }
    }

    /// Returns whether the password will be provided externally.
    ///
    /// Returns whether this is [`PasswordSource::ExternalSideEffect`]
    /// or [`PasswordSource::ExternalOnDemand`].
    pub fn is_external_source(&self) -> bool {
        ! self.is_inline()
    }
}
