pub use sequoia_keystore_backend::Protection;

use crate::Result;
use crate::keystore_protocol_capnp::keystore;

impl TryFrom<keystore::protection::Reader<'_>> for Protection {
    type Error = anyhow::Error;

    fn try_from(reader: keystore::protection::Reader<'_>) -> Result<Self> {
        use keystore::protection::Which;

        let extract = |msg: capnp::text::Reader<'_>| -> Result<_> {
            let msg = msg.to_string()?;
            if msg.is_empty() {
                Ok(None)
            } else {
                Ok(Some(msg))
            }
        };

        match reader.which()? {
            Which::Unlocked(()) => Ok(Protection::Unlocked),
            Which::UnknownProtection(msg) => {
                Ok(Protection::UnknownProtection(extract(msg?)?))
            }
            Which::Password(msg) => {
                Ok(Protection::Password(extract(msg?)?))
            }
            Which::ExternalPassword(msg) => {
                Ok(Protection::ExternalPassword(extract(msg?)?))
            }
            Which::ExternalTouch(msg) => {
                Ok(Protection::ExternalTouch(extract(msg?)?))
            }
            Which::ExternalOther(msg) => {
                Ok(Protection::ExternalOther(extract(msg?)?))
            }
        }
    }
}

impl keystore::protection::Builder<'_> {
    /// Serialize Protection.
    pub fn set_protection(&mut self, protection: Protection) -> Result<()> {
        match protection {
            Protection::Unlocked => self.set_unlocked(()),
            Protection::UnknownProtection(msg) => {
                self.set_unknown_protection(
                    msg.as_deref().unwrap_or(""))
            }
            Protection::Password(msg) => {
                self.set_password(
                    msg.as_deref().unwrap_or(""))
            }
            Protection::ExternalPassword(msg) => {
                self.set_external_password(
                    msg.as_deref().unwrap_or(""))
            }
            Protection::ExternalTouch(msg) => {
                self.set_external_touch(
                    msg.as_deref().unwrap_or(""))
            }
            Protection::ExternalOther(msg) => {
                self.set_external_other(
                    msg.as_deref().unwrap_or(""))
            }
        }

        Ok(())
    }
}
