//! Components needed to verify TUF metadata and targets.

use chrono::offset::Utc;
use log::info;
use std::collections::{HashMap, HashSet};
use std::marker::PhantomData;

use crate::crypto::KeyId;
use crate::error::Error;
use crate::interchange::DataInterchange;
use crate::metadata::{
    Delegations, Metadata, MetadataPath, Role, RootMetadata, SignedMetadata, SnapshotMetadata,
    TargetDescription, TargetsMetadata, TimestampMetadata, VirtualTargetPath,
};
use crate::Result;

/// Contains trusted TUF metadata and can be used to verify other metadata and targets.
#[derive(Debug)]
pub struct Tuf<D: DataInterchange> {
    root: SignedMetadata<D, RootMetadata>,
    snapshot: Option<SignedMetadata<D, SnapshotMetadata>>,
    targets: Option<SignedMetadata<D, TargetsMetadata>>,
    timestamp: Option<SignedMetadata<D, TimestampMetadata>>,
    delegations: HashMap<MetadataPath, SignedMetadata<D, TargetsMetadata>>,
    interchange: PhantomData<D>,
}

impl<D: DataInterchange> Tuf<D> {
    /// Create a new `TUF` struct from a known set of pinned root keys that are used to verify the
    /// signed metadata.
    pub fn from_root_pinned<'a, I>(
        mut signed_root: SignedMetadata<D, RootMetadata>,
        root_key_ids: I,
    ) -> Result<Self>
    where
        I: IntoIterator<Item = &'a KeyId>,
    {
        let root_key_ids = root_key_ids.into_iter().collect::<HashSet<&KeyId>>();

        signed_root
            .signatures_mut()
            .retain(|s| root_key_ids.contains(s.key_id()));
        Self::from_root(signed_root)
    }

    /// Create a new `TUF` struct from a piece of metadata that is assumed to be trusted.
    ///
    /// **WARNING**: This is trust-on-first-use (TOFU) and offers weaker security guarantees than
    /// the related method `from_root_pinned`.
    pub fn from_root(signed_root: SignedMetadata<D, RootMetadata>) -> Result<Self> {
        {
            let root = signed_root.as_ref();
            signed_root.verify(
                root.root().threshold(),
                root.keys().iter().filter_map(|(k, v)| {
                    if root.root().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;
        }
        Ok(Tuf {
            root: signed_root,
            snapshot: None,
            targets: None,
            timestamp: None,
            delegations: HashMap::new(),
            interchange: PhantomData,
        })
    }

    /// An immutable reference to the root metadata.
    pub fn root(&self) -> &RootMetadata {
        self.root.as_ref()
    }

    /// An immutable reference to the optional snapshot metadata.
    pub fn snapshot(&self) -> Option<&SnapshotMetadata> {
        self.snapshot.as_ref().map(|t| t.as_ref())
    }

    /// An immutable reference to the optional targets metadata.
    pub fn targets(&self) -> Option<&TargetsMetadata> {
        self.targets.as_ref().map(|t| t.as_ref())
    }

    /// An immutable reference to the optional timestamp metadata.
    pub fn timestamp(&self) -> Option<&TimestampMetadata> {
        self.timestamp.as_ref().map(|t| t.as_ref())
    }

    /// An immutable reference to the delegated metadata.
    pub fn delegations(&self) -> &HashMap<MetadataPath, SignedMetadata<D, TargetsMetadata>> {
        &self.delegations
    }

    /// An immutable reference to the root metadata.
    pub fn signed_root(&self) -> &SignedMetadata<D, RootMetadata> {
        &self.root
    }

    /// An immutable reference to the optional snapshot metadata.
    pub fn signed_snapshot(&self) -> Option<&SignedMetadata<D, SnapshotMetadata>> {
        self.snapshot.as_ref()
    }

    /// An immutable reference to the optional targets metadata.
    pub fn signed_targets(&self) -> Option<&SignedMetadata<D, TargetsMetadata>> {
        self.targets.as_ref()
    }

    /// An immutable reference to the optional timestamp metadata.
    pub fn signed_timestamp(&self) -> Option<&SignedMetadata<D, TimestampMetadata>> {
        self.timestamp.as_ref()
    }

    fn current_timestamp_version(&self) -> u32 {
        self.timestamp
            .as_ref()
            .map(|t| t.as_ref().version())
            .unwrap_or(0)
    }

    fn current_snapshot_version(&self) -> u32 {
        self.snapshot
            .as_ref()
            .map(|t| t.as_ref().version())
            .unwrap_or(0)
    }

    fn current_targets_version(&self) -> u32 {
        self.targets
            .as_ref()
            .map(|t| t.as_ref().version())
            .unwrap_or(0)
    }

    fn current_delegation_version(&self, role: &MetadataPath) -> u32 {
        self.delegations
            .get(role)
            .map(|t| t.as_ref().version())
            .unwrap_or(0)
    }

    /// Verify and update the root metadata.
    pub fn update_root(&mut self, signed_root: SignedMetadata<D, RootMetadata>) -> Result<bool> {
        {
            let old_root = self.root.as_ref();
            let new_root = signed_root.as_ref();

            // First, check that the new root was signed by the old root.
            signed_root.verify(
                old_root.root().threshold(),
                old_root.keys().iter().filter_map(|(k, v)| {
                    if old_root.root().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;

            // Next, make sure the new root has a higher version than the old root.
            if new_root.version() == old_root.version() {
                info!(
                    "Attempted to update root to new metadata with the same version. \
                     Refusing to update."
                );
                return Ok(false);
            } else if new_root.version() < old_root.version() {
                return Err(Error::VerificationFailure(format!(
                    "Attempted to roll back root metadata at version {} to {}.",
                    old_root.version(),
                    new_root.version()
                )));
            }

            // Finally, make sure the new root was signed by the keys in the new root.
            signed_root.verify(
                new_root.root().threshold(),
                new_root.keys().iter().filter_map(|(k, v)| {
                    if new_root.root().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;
        }

        self.purge_metadata();

        self.root = signed_root;
        Ok(true)
    }

    /// Verify and update the timestamp metadata.
    pub fn update_timestamp(
        &mut self,
        signed_timestamp: SignedMetadata<D, TimestampMetadata>,
    ) -> Result<bool> {
        {
            let root = self.root.as_ref();
            let timestamp = signed_timestamp.as_ref();

            // First, make sure the root signed the metadata.
            signed_timestamp.verify(
                root.timestamp().threshold(),
                root.keys().iter().filter_map(|(k, v)| {
                    if root.timestamp().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;

            // Next, make sure the timestamp hasn't expired.
            if timestamp.expires() <= &Utc::now() {
                return Err(Error::ExpiredMetadata(Role::Timestamp));
            }

            // Next, make sure the new metadata has a higher version than the old metadata.
            let current_version = self.current_timestamp_version();

            if timestamp.version() < current_version {
                return Err(Error::VerificationFailure(format!(
                    "Attempted to roll back timestamp metadata at version {} to {}.",
                    current_version,
                    timestamp.version()
                )));
            } else if timestamp.version() == current_version {
                return Ok(false);
            }

            if self.current_snapshot_version() != timestamp.snapshot().version() {
                self.snapshot = None;
            }
        }

        self.timestamp = Some(signed_timestamp);
        Ok(true)
    }

    /// Verify and update the snapshot metadata.
    pub fn update_snapshot(
        &mut self,
        signed_snapshot: SignedMetadata<D, SnapshotMetadata>,
    ) -> Result<bool> {
        {
            let root = self.safe_root_ref()?;
            let timestamp = self.safe_timestamp_ref()?;
            let current_version = self.current_snapshot_version();

            if timestamp.snapshot().version() < current_version {
                return Err(Error::VerificationFailure(format!(
                    "Attempted to roll back snapshot metadata at version {} to {}.",
                    current_version,
                    timestamp.snapshot().version()
                )));
            } else if timestamp.snapshot().version() == current_version {
                return Ok(false);
            }

            signed_snapshot.verify(
                root.snapshot().threshold(),
                self.root.as_ref().keys().iter().filter_map(|(k, v)| {
                    if root.snapshot().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;

            let snapshot = signed_snapshot.as_ref();

            if snapshot.version() != timestamp.snapshot().version() {
                return Err(Error::VerificationFailure(format!(
                    "The timestamp metadata reported that the snapshot metadata should be at \
                     version {} but version {} was found instead.",
                    timestamp.snapshot().version(),
                    snapshot.version()
                )));
            }

            // Note: this doesn't check the expiration because we need to be able to update it
            // regardless so we can prevent rollback attacks againsts targets/delegations.
        };

        if self
            .targets
            .as_ref()
            .map(|s| s.as_ref().version())
            .unwrap_or(0)
            != signed_snapshot
                .as_ref()
                .meta()
                .get(&MetadataPath::from_role(&Role::Targets))
                .map(|m| m.version())
                .unwrap_or(0)
        {
            self.targets = None;
        }

        self.snapshot = Some(signed_snapshot);
        self.purge_delegations();
        Ok(true)
    }

    fn purge_delegations(&mut self) {
        let purge = {
            let snapshot = match self.snapshot() {
                Some(s) => s,
                None => return,
            };
            let mut purge = HashSet::new();
            for (role, definition) in snapshot.meta().iter() {
                let delegation = match self.delegations.get(role) {
                    Some(d) => d,
                    None => continue,
                };

                if delegation.as_ref().version() > definition.version() {
                    let _ = purge.insert(role.clone());
                    continue;
                }
            }

            purge
        };

        for role in &purge {
            let _ = self.delegations.remove(role);
        }
    }

    /// Verify and update the targets metadata.
    pub fn update_targets(
        &mut self,
        signed_targets: SignedMetadata<D, TargetsMetadata>,
    ) -> Result<bool> {
        {
            let root = self.safe_root_ref()?;
            let snapshot = self.safe_snapshot_ref()?;
            let targets_description = snapshot
                .meta()
                .get(&MetadataPath::from_role(&Role::Targets))
                .ok_or_else(|| {
                    Error::VerificationFailure(
                        "Snapshot metadata had no description of the targets metadata".into(),
                    )
                })?;

            let current_version = self.current_targets_version();

            if targets_description.version() < current_version {
                return Err(Error::VerificationFailure(format!(
                    "Attempted to roll back targets metadata at version {} to {}.",
                    current_version,
                    targets_description.version()
                )));
            } else if targets_description.version() == current_version {
                return Ok(false);
            }

            signed_targets.verify(
                root.targets().threshold(),
                root.keys().iter().filter_map(|(k, v)| {
                    if root.targets().key_ids().contains(k) {
                        Some(v)
                    } else {
                        None
                    }
                }),
            )?;

            let targets = signed_targets.as_ref();

            if targets.version() != targets_description.version() {
                return Err(Error::VerificationFailure(format!(
                    "The timestamp metadata reported that the targets metadata should be at \
                     version {} but version {} was found instead.",
                    targets_description.version(),
                    targets.version()
                )));
            }

            if targets.expires() <= &Utc::now() {
                return Err(Error::ExpiredMetadata(Role::Snapshot));
            }
        }

        self.targets = Some(signed_targets);
        Ok(true)
    }

    /// Verify and update a delegation metadata.
    pub fn update_delegation(
        &mut self,
        role: &MetadataPath,
        signed_delegation: SignedMetadata<D, TargetsMetadata>,
    ) -> Result<bool> {
        {
            let _ = self.safe_root_ref()?;
            let snapshot = self.safe_snapshot_ref()?;
            let targets = self.safe_targets_ref()?;
            let targets_delegations = match targets.delegations() {
                Some(d) => d,
                None => {
                    return Err(Error::VerificationFailure(
                        "Delegations not authorized".into(),
                    ));
                }
            };

            let delegation_description = match snapshot.meta().get(role) {
                Some(d) => d,
                None => {
                    return Err(Error::VerificationFailure(format!(
                        "The degated role {:?} was not present in the snapshot metadata.",
                        role
                    )));
                }
            };

            let current_version = self.current_delegation_version(role);

            if delegation_description.version() < current_version {
                return Err(Error::VerificationFailure(format!(
                    "Snapshot metadata did listed delegation {:?} version as {} but current\
                     version is {}",
                    role,
                    delegation_description.version(),
                    current_version
                )));
            } else if current_version == delegation_description.version() {
                return Ok(false);
            }

            for delegated_targets in self.delegations.values() {
                let parent = match delegated_targets.as_ref().delegations() {
                    Some(d) => d,
                    None => &targets_delegations,
                };

                let delegation = match parent.roles().iter().find(|r| r.role() == role) {
                    Some(d) => d,
                    None => continue,
                };

                signed_delegation.verify(
                    delegation.threshold(),
                    parent.keys().iter().filter_map(|(k, v)| {
                        if delegation.key_ids().contains(k) {
                            Some(v)
                        } else {
                            None
                        }
                    }),
                )?;
            }

            let delegation = signed_delegation.as_ref();
            if delegation.version() != delegation_description.version() {
                return Err(Error::VerificationFailure(format!(
                    "The snapshot metadata reported that the delegation {:?} should be at \
                     version {} but version {} was found instead.",
                    role,
                    delegation_description.version(),
                    delegation.version(),
                )));
            }

            if delegation.expires() <= &Utc::now() {
                // TODO this needs to be chagned to accept a MetadataPath and not Role
                return Err(Error::ExpiredMetadata(Role::Targets));
            }
        }

        let _ = self.delegations.insert(role.clone(), signed_delegation);

        Ok(true)
    }

    /// Get a reference to the description needed to verify the target defined by the given
    /// `VirtualTargetPath`. Returns an `Error` if the target is not defined in the trusted
    /// metadata. This may mean the target exists somewhere in the metadata, but the chain of trust
    /// to that target may be invalid or incomplete.
    pub fn target_description(&self, target_path: &VirtualTargetPath) -> Result<TargetDescription> {
        let _ = self.safe_root_ref()?;
        let _ = self.safe_snapshot_ref()?;
        let targets = self.safe_targets_ref()?;

        if let Some(d) = targets.targets().get(target_path) {
            return Ok(d.clone());
        }

        fn lookup<D: DataInterchange>(
            tuf: &Tuf<D>,
            default_terminate: bool,
            current_depth: u32,
            target_path: &VirtualTargetPath,
            delegations: &Delegations,
            parents: &[HashSet<VirtualTargetPath>],
            visited: &mut HashSet<MetadataPath>,
        ) -> (bool, Option<TargetDescription>) {
            for delegation in delegations.roles() {
                if visited.contains(delegation.role()) {
                    return (delegation.terminating(), None);
                }
                let _ = visited.insert(delegation.role().clone());

                let mut new_parents = parents.to_owned();
                new_parents.push(delegation.paths().clone());

                if current_depth > 0 && !target_path.matches_chain(&parents) {
                    return (delegation.terminating(), None);
                }

                let targets = match tuf.delegations.get(delegation.role()) {
                    Some(t) => t.as_ref(),
                    None => return (delegation.terminating(), None),
                };

                if targets.expires() <= &Utc::now() {
                    return (delegation.terminating(), None);
                }

                if let Some(d) = targets.targets().get(target_path) {
                    return (delegation.terminating(), Some(d.clone()));
                }

                if let Some(d) = targets.delegations() {
                    let mut new_parents = parents.to_vec();
                    new_parents.push(delegation.paths().clone());
                    let (term, res) = lookup(
                        tuf,
                        delegation.terminating(),
                        current_depth + 1,
                        target_path,
                        d,
                        &new_parents,
                        visited,
                    );
                    if term {
                        return (true, res);
                    } else if res.is_some() {
                        return (term, res);
                    }
                }
            }
            (default_terminate, None)
        }

        match targets.delegations() {
            Some(d) => {
                let mut visited = HashSet::new();
                lookup(self, false, 0, target_path, d, &[], &mut visited)
                    .1
                    .ok_or_else(|| Error::TargetUnavailable)
            }
            None => Err(Error::TargetUnavailable),
        }
    }

    fn purge_metadata(&mut self) {
        self.snapshot = None;
        self.targets = None;
        self.timestamp = None;
        self.delegations.clear();
    }

    fn safe_root_ref(&self) -> Result<&RootMetadata> {
        let root = self.root.as_ref();
        if root.expires() <= &Utc::now() {
            return Err(Error::ExpiredMetadata(Role::Root));
        }
        Ok(&root)
    }

    fn safe_snapshot_ref(&self) -> Result<&SnapshotMetadata> {
        match self.snapshot {
            Some(ref snapshot) => {
                let snapshot = snapshot.as_ref();
                if snapshot.expires() <= &Utc::now() {
                    return Err(Error::ExpiredMetadata(Role::Snapshot));
                }
                Ok(snapshot)
            }
            None => Err(Error::MissingMetadata(Role::Snapshot)),
        }
    }

    fn safe_targets_ref(&self) -> Result<&TargetsMetadata> {
        match self.targets {
            Some(ref targets) => {
                let targets = targets.as_ref();
                if targets.expires() <= &Utc::now() {
                    return Err(Error::ExpiredMetadata(Role::Targets));
                }
                Ok(targets)
            }
            None => Err(Error::MissingMetadata(Role::Targets)),
        }
    }
    fn safe_timestamp_ref(&self) -> Result<&TimestampMetadata> {
        match self.timestamp {
            Some(ref timestamp) => {
                let timestamp = timestamp.as_ref();
                if timestamp.expires() <= &Utc::now() {
                    return Err(Error::ExpiredMetadata(Role::Timestamp));
                }
                Ok(timestamp)
            }
            None => Err(Error::MissingMetadata(Role::Timestamp)),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
    use crate::interchange::Json;
    use crate::metadata::{
        RootMetadataBuilder, SnapshotMetadataBuilder, TargetsMetadataBuilder,
        TimestampMetadataBuilder,
    };
    use lazy_static::lazy_static;

    lazy_static! {
        static ref KEYS: Vec<PrivateKey> = {
            let keys: &[&[u8]] = &[
                include_bytes!("../tests/ed25519/ed25519-1.pk8.der"),
                include_bytes!("../tests/ed25519/ed25519-2.pk8.der"),
                include_bytes!("../tests/ed25519/ed25519-3.pk8.der"),
                include_bytes!("../tests/ed25519/ed25519-4.pk8.der"),
                include_bytes!("../tests/ed25519/ed25519-5.pk8.der"),
                include_bytes!("../tests/ed25519/ed25519-6.pk8.der"),
            ];
            keys.iter()
                .map(|b| PrivateKey::from_pkcs8(b, SignatureScheme::Ed25519).unwrap())
                .collect()
        };
    }

    #[test]
    fn root_pinned_success() {
        let root_key = &KEYS[0];
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[0].public().clone())
            .targets_key(KEYS[0].public().clone())
            .timestamp_key(KEYS[0].public().clone())
            .signed::<Json>(&root_key)
            .unwrap();

        assert!(Tuf::from_root_pinned(root, &[root_key.key_id().clone()]).is_ok());
    }

    #[test]
    fn root_pinned_failure() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[0].public().clone())
            .targets_key(KEYS[0].public().clone())
            .timestamp_key(KEYS[0].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        assert!(Tuf::from_root_pinned(root, &[KEYS[1].key_id().clone()]).is_err());
    }

    #[test]
    fn good_root_rotation() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[0].public().clone())
            .targets_key(KEYS[0].public().clone())
            .timestamp_key(KEYS[0].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let mut root = RootMetadataBuilder::new()
            .version(2)
            .root_key(KEYS[1].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[1].public().clone())
            .timestamp_key(KEYS[1].public().clone())
            .signed::<Json>(&KEYS[1])
            .unwrap();

        // add the original key's signature to make it cross signed
        root.add_signature(&KEYS[0]).unwrap();

        assert_eq!(tuf.update_root(root.clone()), Ok(true));

        // second update should do nothing
        assert_eq!(tuf.update_root(root), Ok(false));
    }

    #[test]
    fn no_cross_sign_root_rotation() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[0].public().clone())
            .targets_key(KEYS[0].public().clone())
            .timestamp_key(KEYS[0].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let root = RootMetadataBuilder::new()
            .root_key(KEYS[1].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[1].public().clone())
            .timestamp_key(KEYS[1].public().clone())
            .signed::<Json>(&KEYS[1])
            .unwrap();

        assert!(tuf.update_root(root).is_err());
    }

    #[test]
    fn good_timestamp_update() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[1].public().clone())
            .timestamp_key(KEYS[1].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .signed::<Json>(&KEYS[1])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[1])
                .unwrap();

        assert_eq!(tuf.update_timestamp(timestamp.clone()), Ok(true));

        // second update should do nothing
        assert_eq!(tuf.update_timestamp(timestamp), Ok(false))
    }

    #[test]
    fn bad_timestamp_update_wrong_key() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[1].public().clone())
            .timestamp_key(KEYS[1].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .signed::<Json>(&KEYS[1])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                // sign it with the root key
                .signed::<Json>(&KEYS[0])
                .unwrap();

        assert!(tuf.update_timestamp(timestamp).is_err())
    }

    #[test]
    fn good_snapshot_update() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[2].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let snapshot = SnapshotMetadataBuilder::new().signed(&KEYS[1]).unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[2])
                .unwrap();

        tuf.update_timestamp(timestamp).unwrap();

        assert_eq!(tuf.update_snapshot(snapshot.clone()), Ok(true));

        // second update should do nothing
        assert_eq!(tuf.update_snapshot(snapshot), Ok(false));
    }

    #[test]
    fn bad_snapshot_update_wrong_key() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[2].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .signed::<Json>(&KEYS[2])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                // sign it with the targets key
                .signed::<Json>(&KEYS[2])
                .unwrap();

        tuf.update_timestamp(timestamp).unwrap();

        assert!(tuf.update_snapshot(snapshot).is_err());
    }

    #[test]
    fn bad_snapshot_update_wrong_version() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[2].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .version(2)
            .signed::<Json>(&KEYS[2])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[2])
                .unwrap();

        tuf.update_timestamp(timestamp).unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .version(1)
            .signed::<Json>(&KEYS[1])
            .unwrap();

        assert!(tuf.update_snapshot(snapshot).is_err());
    }

    #[test]
    fn good_targets_update() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[3].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let targets = TargetsMetadataBuilder::new()
            .signed::<Json>(&KEYS[2])
            .unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .insert_metadata(&targets, &[HashAlgorithm::Sha256])
            .unwrap()
            .signed::<Json>(&KEYS[1])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[3])
                .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        tuf.update_timestamp(timestamp).unwrap();
        tuf.update_snapshot(snapshot).unwrap();

        assert_eq!(tuf.update_targets(targets.clone()), Ok(true));

        // second update should do nothing
        assert_eq!(tuf.update_targets(targets), Ok(false));
    }

    #[test]
    fn bad_targets_update_wrong_key() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[3].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let targets = TargetsMetadataBuilder::new()
            // sign it with the timestamp key
            .signed::<Json>(&KEYS[3])
            .unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .insert_metadata(&targets, &[HashAlgorithm::Sha256])
            .unwrap()
            .signed::<Json>(&KEYS[1])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[3])
                .unwrap();

        tuf.update_timestamp(timestamp).unwrap();
        tuf.update_snapshot(snapshot).unwrap();

        assert!(tuf.update_targets(targets).is_err());
    }

    #[test]
    fn bad_targets_update_wrong_version() {
        let root = RootMetadataBuilder::new()
            .root_key(KEYS[0].public().clone())
            .snapshot_key(KEYS[1].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[3].public().clone())
            .signed::<Json>(&KEYS[0])
            .unwrap();

        let mut tuf = Tuf::from_root(root).unwrap();

        let targets = TargetsMetadataBuilder::new()
            .version(2)
            .signed::<Json>(&KEYS[2])
            .unwrap();

        let snapshot = SnapshotMetadataBuilder::new()
            .insert_metadata(&targets, &[HashAlgorithm::Sha256])
            .unwrap()
            .signed::<Json>(&KEYS[1])
            .unwrap();

        let timestamp =
            TimestampMetadataBuilder::from_snapshot(&snapshot, &[HashAlgorithm::Sha256])
                .unwrap()
                .signed::<Json>(&KEYS[3])
                .unwrap();

        tuf.update_timestamp(timestamp).unwrap();
        tuf.update_snapshot(snapshot).unwrap();

        let targets = TargetsMetadataBuilder::new()
            .version(1)
            .signed::<Json>(&KEYS[2])
            .unwrap();

        assert!(tuf.update_targets(targets).is_err());
    }
}
