use std::fmt;

use sequoia_openpgp as openpgp;
use openpgp::packet::UserID;
use openpgp::cert::prelude::*;

use crate::RevocationStatus;

/// Encapsulates an OpenPGP User ID.
///
/// This holds the information about a User ID that is relevant to web
/// of trust calculations.
#[derive(Debug, Clone)]
pub struct UserIDSynopsis {
    userid: UserID,
    revocation_status: RevocationStatus,
}

impl<'a> From<&ValidUserIDAmalgamation<'a>> for UserIDSynopsis {
    fn from(ua: &ValidUserIDAmalgamation<'a>) -> Self {
        UserIDSynopsis {
            userid: ua.userid().clone(),
            revocation_status: ua.revocation_status().into(),
        }
    }
}

impl<'a> From<ValidUserIDAmalgamation<'a>> for UserIDSynopsis {
    fn from(ua: ValidUserIDAmalgamation<'a>) -> Self {
        (&ua).into()
    }
}

impl<'a> From<&[u8]> for UserIDSynopsis {
    fn from(userid: &[u8]) -> Self {
        UserIDSynopsis {
            userid: UserID::from(userid),
            revocation_status: RevocationStatus::NotAsFarAsWeKnow,
        }
    }
}

impl<'a> From<&str> for UserIDSynopsis {
    fn from(userid: &str) -> Self {
        userid.as_bytes().into()
    }
}

impl<'a> From<UserID> for UserIDSynopsis {
    fn from(userid: UserID) -> Self {
        UserIDSynopsis {
            userid,
            revocation_status: RevocationStatus::NotAsFarAsWeKnow,
        }
    }
}

impl fmt::Display for UserIDSynopsis {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_fmt(
            format_args!(
                "{} ({})",
                String::from_utf8_lossy(self.userid.value()),
                match self.revocation_status {
                    RevocationStatus::NotAsFarAsWeKnow => "",
                    RevocationStatus::Hard =>
                        "hard revoked",
                    RevocationStatus::Soft(_t) =>
                        "soft revoked",
                }))
    }
}

impl UserIDSynopsis {
    /// Returns a new UserIDSynopsis.
    pub fn new<U, R>(userid: U, revocation_status: R) -> Self
    where U: Into<UserID>,
          R: Into<RevocationStatus>,
    {
        Self {
            userid: userid.into(),
            revocation_status: revocation_status.into(),
        }
    }

    /// Returns the User ID.
    pub fn userid(&self) -> &UserID {
        &self.userid
    }

    /// Returns the User ID's value.
    pub fn value(&self) -> &[u8] {
        &self.userid.value()
    }

    /// Returns the certificate's revocation status.
    pub fn revocation_status(&self) -> RevocationStatus {
        self.revocation_status.clone()
    }
}
