//! Clients for high level interactions with TUF repositories.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await, await_macro, futures_api)]
//! # use futures::executor::block_on;
//! # use hyper::client::Client as HttpClient;
//! # use std::path::PathBuf;
//! # use tuf::{Result, Tuf};
//! # use tuf::crypto::KeyId;
//! # use tuf::client::{Client, Config};
//! # use tuf::metadata::{RootMetadata, SignedMetadata, Role, MetadataPath,
//! #     MetadataVersion};
//! # use tuf::interchange::Json;
//! # use tuf::repository::{Repository, FileSystemRepository, HttpRepositoryBuilder};
//!
//! static TRUSTED_ROOT_KEY_IDS: &'static [&str] = &[
//!     "diNfThTFm0PI8R-Bq7NztUIvZbZiaC_weJBgcqaHlWw=",
//!     "ar9AgoRsmeEcf6Ponta_1TZu1ds5uXbDemBig30O7ck=",
//!     "T5vfRrM1iHpgzGwAHe7MbJH_7r4chkOAphV3OPCCv0I=",
//! ];
//!
//! # fn main() -> Result<()> {
//! # block_on(async {
//! let key_ids: Vec<KeyId> = TRUSTED_ROOT_KEY_IDS.iter()
//!     .map(|k| KeyId::from_string(k).unwrap())
//!     .collect();
//!
//! let local = FileSystemRepository::<Json>::new(PathBuf::from("~/.rustup"))?;
//!
//! let remote = HttpRepositoryBuilder::new(
//!     url::Url::parse("https://static.rust-lang.org/").unwrap(),
//!     HttpClient::new(),
//! )
//! .user_agent_prefix("rustup/1.4.0")
//! .build();
//!
//! let mut client = await!(Client::with_root_pinned(
//!     &key_ids,
//!     Config::default(),
//!     local,
//!     remote,
//! ))?;
//!
//! let _ = await!(client.update())?;
//! # Ok(())
//! # })
//! # }
//! ```

use chrono::offset::Utc;
use futures::io::{AsyncRead, AsyncReadExt, AsyncWrite};
use log::{error, warn};

use crate::crypto::{self, KeyId};
use crate::error::Error;
use crate::interchange::DataInterchange;
use crate::metadata::{
    Metadata, MetadataPath, MetadataVersion, Role, SignedMetadata, SnapshotMetadata,
    TargetDescription, TargetPath, TargetsMetadata, VirtualTargetPath,
};
use crate::repository::Repository;
use crate::tuf::Tuf;
use crate::{Result, TufFuture};

/// Translates real paths (where a file is stored) into virtual paths (how it is addressed in TUF)
/// and back.
///
/// Implementations must obey the following identities for all possible inputs.
///
/// ```
/// # use tuf::client::{PathTranslator, DefaultTranslator};
/// # use tuf::metadata::{VirtualTargetPath, TargetPath};
/// let path = TargetPath::new("foo".into()).unwrap();
/// let virt = VirtualTargetPath::new("foo".into()).unwrap();
/// let translator = DefaultTranslator::new();
/// assert_eq!(path,
///            translator.virtual_to_real(&translator.real_to_virtual(&path).unwrap()).unwrap());
/// assert_eq!(virt,
///            translator.real_to_virtual(&translator.virtual_to_real(&virt).unwrap()).unwrap());
/// ```
pub trait PathTranslator {
    /// Convert a real path into a virtual path.
    fn real_to_virtual(&self, path: &TargetPath) -> Result<VirtualTargetPath>;

    /// Convert a virtual path into a real path.
    fn virtual_to_real(&self, path: &VirtualTargetPath) -> Result<TargetPath>;
}

/// A `PathTranslator` that does nothing.
#[derive(Default)]
pub struct DefaultTranslator;

impl DefaultTranslator {
    /// Create a new `DefaultTranslator`.
    pub fn new() -> Self {
        DefaultTranslator
    }
}

impl PathTranslator for DefaultTranslator {
    fn real_to_virtual(&self, path: &TargetPath) -> Result<VirtualTargetPath> {
        VirtualTargetPath::new(path.value().into())
    }

    fn virtual_to_real(&self, path: &VirtualTargetPath) -> Result<TargetPath> {
        TargetPath::new(path.value().into())
    }
}

/// A client that interacts with TUF repositories.
pub struct Client<D, L, R, T>
where
    D: DataInterchange,
    L: Repository<D>,
    R: Repository<D>,
    T: PathTranslator,
{
    tuf: Tuf<D>,
    config: Config<T>,
    local: L,
    remote: R,
}

impl<D, L, R, T> Client<D, L, R, T>
where
    D: DataInterchange,
    L: Repository<D> + 'static,
    R: Repository<D> + 'static,
    T: PathTranslator + 'static,
{
    /// Create a new TUF client. It will attempt to load initial root metadata from the local repo
    /// and return an error if it cannot do so.
    ///
    /// **WARNING**: This method offers weaker security guarantees than the related method
    /// `with_root_pinned`.
    pub async fn new(config: Config<T>, local: L, remote: R) -> Result<Self> {
        let root_path = MetadataPath::from_role(&Role::Root);
        let root_version = MetadataVersion::Number(1);

        let root = await!(local.fetch_metadata(
            &root_path,
            &root_version,
            &config.max_root_size,
            None,
        ))?;

        let tuf = Tuf::from_root(root)?;

        Ok(Client {
            tuf,
            config,
            local,
            remote,
        })
    }

    /// Create a new TUF client. It will attempt to load initial root metadata the local and remote
    /// repositories using the provided key IDs to pin the verification.
    ///
    /// This is the preferred method of creating a client.
    pub async fn with_root_pinned(
        trusted_root_keys: &[KeyId],
        config: Config<T>,
        local: L,
        remote: R,
    ) -> Result<Self> {
        let root_path = MetadataPath::from_role(&Role::Root);
        let root_version = MetadataVersion::Number(1);

        let root = match await!(local.fetch_metadata(
            &root_path,
            &root_version,
            &config.max_root_size,
            None,
        )) {
            Ok(root) => root,
            Err(_) => {
                // FIXME: should we be fetching the latest version instead of version 1?
                let root = await!(remote.fetch_metadata(
                    &root_path,
                    &root_version,
                    &config.max_root_size,
                    None,
                ))?;

                await!(local.store_metadata(&root_path, &MetadataVersion::Number(1), &root))?;

                // FIXME: should we also the root as `MetadataVersion::None`?

                root
            }
        };

        let tuf = Tuf::from_root_pinned(root, trusted_root_keys)?;

        Ok(Client {
            tuf,
            config,
            local,
            remote,
        })
    }

    /// Update TUF metadata from the remote repository.
    ///
    /// Returns `true` if an update occurred and `false` otherwise.
    pub async fn update(&mut self) -> Result<bool> {
        let r = await!(self.update_root())?;
        let ts = await!(self.update_timestamp())?;
        let sn = await!(self.update_snapshot())?;
        let ta = await!(self.update_targets())?;

        Ok(r || ts || sn || ta)
    }

    /// Store the metadata in the local repository. This is juts a local cache, so we ignore if it
    /// experiences any errors.
    async fn store_metadata<'a, M>(
        &'a mut self,
        path: &'a MetadataPath,
        version: &'a MetadataVersion,
        metadata: &'a SignedMetadata<D, M>,
    ) where
        M: Metadata + 'static,
    {
        match await!(self.local.store_metadata(path, version, metadata)) {
            Ok(()) => {}
            Err(err) => {
                warn!(
                    "failed to store {} metadata version {:?} to {}: {}",
                    M::ROLE.name(),
                    version,
                    path.to_string(),
                    err,
                );
            }
        }
    }

    /// Returns `true` if an update occurred and `false` otherwise.
    async fn update_root(&mut self) -> Result<bool> {
        let root_path = MetadataPath::from_role(&Role::Root);

        let latest_root = await!(self.remote.fetch_metadata(
            &root_path,
            &MetadataVersion::None,
            &self.config.max_root_size,
            None,
        ))?;
        let latest_version = latest_root.version();

        if latest_version < self.tuf.root().version() {
            return Err(Error::VerificationFailure(format!(
                "Latest root version is lower than current root version: {} < {}",
                latest_version,
                self.tuf.root().version()
            )));
        } else if latest_version == self.tuf.root().version() {
            return Ok(false);
        }

        let err_msg = "TUF claimed no update occurred when one should have. \
                       This is a programming error. Please report this as a bug.";

        for i in (self.tuf.root().version() + 1)..latest_version {
            let version = MetadataVersion::Number(i);

            let signed_root = await!(self.remote.fetch_metadata(
                &root_path,
                &version,
                &self.config.max_root_size,
                None,
            ))?;

            if !self.tuf.update_root(signed_root.clone())? {
                error!("{}", err_msg);
                return Err(Error::Programming(err_msg.into()));
            }

            await!(self.store_metadata(&root_path, &version, &signed_root));
        }

        if !self.tuf.update_root(latest_root.clone())? {
            error!("{}", err_msg);
            return Err(Error::Programming(err_msg.into()));
        }

        let latest_version = MetadataVersion::Number(latest_version);

        await!(self.store_metadata(&root_path, &latest_version, &latest_root,));
        await!(self.store_metadata(&root_path, &MetadataVersion::None, &latest_root));

        if self.tuf.root().expires() <= &Utc::now() {
            error!("Root metadata expired, potential freeze attack");
            return Err(Error::ExpiredMetadata(Role::Root));
        }

        Ok(true)
    }

    /// Returns `true` if an update occurred and `false` otherwise.
    async fn update_timestamp(&mut self) -> Result<bool> {
        let timestamp_path = MetadataPath::from_role(&Role::Timestamp);

        let signed_timestamp = await!(self.remote.fetch_metadata(
            &timestamp_path,
            &MetadataVersion::None,
            &self.config.max_timestamp_size,
            None,
        ))?;

        if self.tuf.update_timestamp(signed_timestamp.clone())? {
            let latest_version = signed_timestamp.version();
            let latest_version = MetadataVersion::Number(latest_version);

            await!(self.store_metadata(&timestamp_path, &latest_version, &signed_timestamp,));

            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Returns `true` if an update occurred and `false` otherwise.
    async fn update_snapshot(&mut self) -> Result<bool> {
        // 5.3.1 Check against timestamp metadata. The hashes and version number listed in the
        // timestamp metadata. If hashes and version do not match, discard the new snapshot
        // metadata, abort the update cycle, and report the failure.
        let snapshot_description = match self.tuf.timestamp() {
            Some(ts) => Ok(ts.snapshot()),
            None => Err(Error::MissingMetadata(Role::Timestamp)),
        }?
        .clone();

        if snapshot_description.version() <= self.tuf.snapshot().map(|s| s.version()).unwrap_or(0) {
            return Ok(false);
        }

        let (alg, value) = crypto::hash_preference(snapshot_description.hashes())?;

        let version = if self.tuf.root().consistent_snapshot() {
            MetadataVersion::Number(snapshot_description.version())
        } else {
            MetadataVersion::None
        };

        let snapshot_path = MetadataPath::from_role(&Role::Snapshot);
        let snapshot_size = Some(snapshot_description.size());

        let signed_snapshot = await!(self.remote.fetch_metadata(
            &snapshot_path,
            &version,
            &snapshot_size,
            Some((alg, value.clone())),
        ))?;

        if self.tuf.update_snapshot(signed_snapshot.clone())? {
            await!(self.store_metadata(&snapshot_path, &version, &signed_snapshot));

            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Returns `true` if an update occurred and `false` otherwise.
    async fn update_targets(&mut self) -> Result<bool> {
        let targets_description = match self.tuf.snapshot() {
            Some(sn) => match sn.meta().get(&MetadataPath::from_role(&Role::Targets)) {
                Some(d) => Ok(d),
                None => Err(Error::VerificationFailure(
                    "Snapshot metadata did not contain a description of the \
                     current targets metadata."
                        .into(),
                )),
            },
            None => Err(Error::MissingMetadata(Role::Snapshot)),
        }?
        .clone();

        if targets_description.version() <= self.tuf.targets().map(|t| t.version()).unwrap_or(0) {
            return Ok(false);
        }

        let (alg, value) = crypto::hash_preference(targets_description.hashes())?;

        let version = if self.tuf.root().consistent_snapshot() {
            MetadataVersion::Hash(value.clone())
        } else {
            MetadataVersion::None
        };

        let targets_path = MetadataPath::from_role(&Role::Targets);
        let targets_size = Some(targets_description.size());

        let signed_targets = await!(self.remote.fetch_metadata(
            &targets_path,
            &version,
            &targets_size,
            Some((alg, value.clone())),
        ))?;

        if self.tuf.update_targets(signed_targets.clone())? {
            await!(self.store_metadata(&targets_path, &version, &signed_targets));

            Ok(true)
        } else {
            Ok(false)
        }
    }

    /// Fetch a target from the remote repo and write it to the local repo.
    pub async fn fetch_target<'a>(&'a mut self, target: &'a TargetPath) -> Result<()> {
        let read = await!(self._fetch_target(target))?;
        await!(self.local.store_target(read, target))
    }

    /// Fetch a target from the remote repo and write it to the provided writer.
    pub async fn fetch_target_to_writer<'a, W: AsyncWrite + 'a>(
        &'a mut self,
        target: &'a TargetPath,
        mut write: W,
    ) -> Result<()> {
        let mut read = await!(self._fetch_target(&target))?;
        await!(read.copy_into(&mut write))?;
        Ok(())
    }

    // TODO this should check the local repo first
    async fn _fetch_target<'a>(&'a mut self, target: &'a TargetPath) -> Result<Box<dyn AsyncRead>> {
        let virt = self.config.path_translator.real_to_virtual(target)?;

        let snapshot = self
            .tuf
            .snapshot()
            .ok_or_else(|| Error::MissingMetadata(Role::Snapshot))?
            .clone();
        let (_, target_description) =
            await!(self.lookup_target_description(false, 0, &virt, &snapshot, None));
        let target_description = target_description?;

        await!(self.remote.fetch_target(
            target,
            &target_description,
        ))
    }

    async fn lookup_target_description<'a>(
        &'a mut self,
        default_terminate: bool,
        current_depth: u32,
        target: &'a VirtualTargetPath,
        snapshot: &'a SnapshotMetadata,
        targets: Option<&'a TargetsMetadata>,
    ) -> (bool, Result<TargetDescription>) {
        if current_depth > self.config.max_delegation_depth {
            warn!(
                "Walking the delegation graph would have exceeded the configured max depth: {}",
                self.config.max_delegation_depth
            );
            return (default_terminate, Err(Error::NotFound));
        }

        // these clones are dumb, but we need immutable values and not references for update
        // tuf in the loop below
        let targets = match targets {
            Some(t) => t.clone(),
            None => match self.tuf.targets() {
                Some(t) => t.clone(),
                None => {
                    return (
                        default_terminate,
                        Err(Error::MissingMetadata(Role::Targets)),
                    );
                }
            },
        };

        if let Some(t) = targets.targets().get(target) {
            return (default_terminate, Ok(t.clone()));
        }

        let delegations = match targets.delegations() {
            Some(d) => d,
            None => return (default_terminate, Err(Error::NotFound)),
        };

        for delegation in delegations.roles().iter() {
            if !delegation.paths().iter().any(|p| target.is_child(p)) {
                if delegation.terminating() {
                    return (true, Err(Error::NotFound));
                } else {
                    continue;
                }
            }

            let role_meta = match snapshot.meta().get(delegation.role()) {
                Some(m) => m,
                None if !delegation.terminating() => continue,
                None => return (true, Err(Error::NotFound)),
            };

            let (alg, value) = match crypto::hash_preference(role_meta.hashes()) {
                Ok(h) => h,
                Err(e) => return (delegation.terminating(), Err(e)),
            };

            let version = if self.tuf.root().consistent_snapshot() {
                MetadataVersion::Hash(value.clone())
            } else {
                MetadataVersion::None
            };

            let role_size = Some(role_meta.size());
            let signed_meta = await!(self.local.fetch_metadata::<TargetsMetadata>(
                delegation.role(),
                &MetadataVersion::None,
                &role_size,
                Some((alg, value.clone())),
            ));

            let signed_meta = match signed_meta {
                Ok(signed_meta) => signed_meta,
                Err(_) => {
                    match await!(self.remote.fetch_metadata::<TargetsMetadata>(
                        delegation.role(),
                        &version,
                        &role_size,
                        Some((alg, value.clone())),
                    )) {
                        Ok(m) => m,
                        Err(ref e) if !delegation.terminating() => {
                            warn!("Failed to fetch metadata {:?}: {:?}", delegation.role(), e);
                            continue;
                        }
                        Err(e) => {
                            warn!("Failed to fetch metadata {:?}: {:?}", delegation.role(), e);
                            return (true, Err(e));
                        }
                    }
                }
            };

            match self
                .tuf
                .update_delegation(delegation.role(), signed_meta.clone())
            {
                Ok(_) => {
                    match await!(self.local.store_metadata(
                        delegation.role(),
                        &MetadataVersion::None,
                        &signed_meta,
                    )) {
                        Ok(_) => (),
                        Err(e) => warn!(
                            "Error storing metadata {:?} locally: {:?}",
                            delegation.role(),
                            e
                        ),
                    }

                    let meta = self
                        .tuf
                        .delegations()
                        .get(delegation.role())
                        .unwrap()
                        .clone();
                    let (term, res) = await!(Box::pin(self.lookup_target_description(
                        delegation.terminating(),
                        current_depth + 1,
                        target,
                        snapshot,
                        Some(meta.as_ref()),
                    )) as TufFuture<(bool, Result<TargetDescription>)>);

                    if term && res.is_err() {
                        return (true, res);
                    }

                    // TODO end recursion early
                }
                Err(_) if !delegation.terminating() => continue,
                Err(e) => return (true, Err(e)),
            };
        }

        (default_terminate, Err(Error::NotFound))
    }
}

/// Configuration for a TUF `Client`.
///
/// # Defaults
///
/// The following values are considered reasonably safe defaults, however these values may change
/// as this crate moves out of beta. If you are concered about them changing, you should use the
/// `ConfigBuilder` and set your own values.
///
/// ```
/// # use tuf::client::{Config, DefaultTranslator};
/// let config = Config::default();
/// assert_eq!(config.max_root_size(), &Some(1024 * 1024));
/// assert_eq!(config.max_timestamp_size(), &Some(32 * 1024));
/// assert_eq!(config.max_delegation_depth(), 8);
/// let _: &DefaultTranslator = config.path_translator();
/// ```
#[derive(Debug)]
pub struct Config<T>
where
    T: PathTranslator,
{
    max_root_size: Option<usize>,
    max_timestamp_size: Option<usize>,
    max_delegation_depth: u32,
    path_translator: T,
}

impl Config<DefaultTranslator> {
    /// Initialize a `ConfigBuilder` with the default values.
    pub fn build() -> ConfigBuilder<DefaultTranslator> {
        ConfigBuilder::default()
    }
}

impl<T> Config<T>
where
    T: PathTranslator,
{
    /// Return the optional maximum root metadata size.
    pub fn max_root_size(&self) -> &Option<usize> {
        &self.max_root_size
    }

    /// Return the optional maximum timestamp metadata size.
    pub fn max_timestamp_size(&self) -> &Option<usize> {
        &self.max_timestamp_size
    }

    /// The maximum number of steps used when walking the delegation graph.
    pub fn max_delegation_depth(&self) -> u32 {
        self.max_delegation_depth
    }

    /// The `PathTranslator`.
    pub fn path_translator(&self) -> &T {
        &self.path_translator
    }
}

impl Default for Config<DefaultTranslator> {
    fn default() -> Self {
        Config {
            max_root_size: Some(1024 * 1024),
            max_timestamp_size: Some(32 * 1024),
            max_delegation_depth: 8,
            path_translator: DefaultTranslator::new(),
        }
    }
}

/// Helper for building and validating a TUF client `Config`.
#[derive(Debug, PartialEq)]
pub struct ConfigBuilder<T>
where
    T: PathTranslator,
{
    max_root_size: Option<usize>,
    max_timestamp_size: Option<usize>,
    max_delegation_depth: u32,
    path_translator: T,
}

impl<T> ConfigBuilder<T>
where
    T: PathTranslator,
{
    /// Validate this builder return a `Config` if validation succeeds.
    pub fn finish(self) -> Result<Config<T>> {
        Ok(Config {
            max_root_size: self.max_root_size,
            max_timestamp_size: self.max_timestamp_size,
            max_delegation_depth: self.max_delegation_depth,
            path_translator: self.path_translator,
        })
    }

    /// Set the optional maximum download size for root metadata.
    pub fn max_root_size(mut self, max: Option<usize>) -> Self {
        self.max_root_size = max;
        self
    }

    /// Set the optional maximum download size for timestamp metadata.
    pub fn max_timestamp_size(mut self, max: Option<usize>) -> Self {
        self.max_timestamp_size = max;
        self
    }

    /// Set the maximum number of steps used when walking the delegation graph.
    pub fn max_delegation_depth(mut self, max: u32) -> Self {
        self.max_delegation_depth = max;
        self
    }

    /// Set the `PathTranslator`.
    pub fn path_translator<TT>(self, path_translator: TT) -> ConfigBuilder<TT>
    where
        TT: PathTranslator,
    {
        ConfigBuilder {
            max_root_size: self.max_root_size,
            max_timestamp_size: self.max_timestamp_size,
            max_delegation_depth: self.max_delegation_depth,
            path_translator,
        }
    }
}

impl Default for ConfigBuilder<DefaultTranslator> {
    fn default() -> ConfigBuilder<DefaultTranslator> {
        let cfg = Config::default();
        ConfigBuilder {
            max_root_size: cfg.max_root_size,
            max_timestamp_size: cfg.max_timestamp_size,
            max_delegation_depth: cfg.max_delegation_depth,
            path_translator: cfg.path_translator,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
    use crate::interchange::Json;
    use crate::metadata::{
        MetadataPath, MetadataVersion, RootMetadata, RootMetadataBuilder, SnapshotMetadataBuilder,
        TargetsMetadataBuilder, TimestampMetadataBuilder,
    };
    use crate::repository::EphemeralRepository;
    use chrono::prelude::*;
    use futures::executor::block_on;
    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_chain_update() {
        let repo = EphemeralRepository::new();

        //// First, create the root metadata.
        let root1 = RootMetadataBuilder::new()
            .version(1)
            .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0))
            .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 root2 = RootMetadataBuilder::new()
            .version(2)
            .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0))
            .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();

        root2.add_signature(&KEYS[0]).unwrap();

        // Make sure the version 2 is signed by version 1's keys.
        root2.add_signature(&KEYS[0]).unwrap();

        let mut root3 = RootMetadataBuilder::new()
            .version(3)
            .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0))
            .root_key(KEYS[2].public().clone())
            .snapshot_key(KEYS[2].public().clone())
            .targets_key(KEYS[2].public().clone())
            .timestamp_key(KEYS[2].public().clone())
            .signed::<Json>(&KEYS[2])
            .unwrap();

        // Make sure the version 3 is signed by version 2's keys.
        root3.add_signature(&KEYS[1]).unwrap();

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

        targets.add_signature(&KEYS[1]).unwrap();
        targets.add_signature(&KEYS[2]).unwrap();

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

        snapshot.add_signature(&KEYS[1]).unwrap();
        snapshot.add_signature(&KEYS[2]).unwrap();

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

        timestamp.add_signature(&KEYS[1]).unwrap();
        timestamp.add_signature(&KEYS[2]).unwrap();

        ////
        // Now register the metadata.

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::Number(1),
            &root1,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::None,
            &root1,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Targets),
            &MetadataVersion::Number(1),
            &targets,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Targets),
            &MetadataVersion::None,
            &targets,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Snapshot),
            &MetadataVersion::Number(1),
            &snapshot,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Snapshot),
            &MetadataVersion::None,
            &snapshot,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Timestamp),
            &MetadataVersion::Number(1),
            &timestamp,
        ))
        .unwrap();

        block_on(repo.store_metadata(
            &MetadataPath::from_role(&Role::Timestamp),
            &MetadataVersion::None,
            &timestamp,
        ))
        .unwrap();

        ////
        // Now, make sure that the local metadata got version 1.

        let key_ids = [KEYS[0].public().key_id().clone()];
        let mut client = block_on(Client::with_root_pinned(
            &key_ids,
            Config::build().finish().unwrap(),
            EphemeralRepository::new(),
            repo,
        ))
        .unwrap();

        assert_eq!(block_on(client.update()), Ok(true));
        assert_eq!(client.tuf.root().version(), 1);

        assert_eq!(
            root1,
            block_on(client.local.fetch_metadata::<RootMetadata>(
                &MetadataPath::from_role(&Role::Root),
                &MetadataVersion::Number(1),
                &None,
                None
            ))
            .unwrap(),
        );

        ////
        // Now bump the root to version 3

        block_on(client.remote.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::Number(2),
            &root2,
        ))
        .unwrap();

        block_on(client.remote.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::None,
            &root2,
        ))
        .unwrap();

        block_on(client.remote.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::Number(3),
            &root3,
        ))
        .unwrap();

        block_on(client.remote.store_metadata(
            &MetadataPath::from_role(&Role::Root),
            &MetadataVersion::None,
            &root3,
        ))
        .unwrap();

        ////
        // Finally, check that the update brings us to version 3.

        assert_eq!(block_on(client.update()), Ok(true));
        assert_eq!(client.tuf.root().version(), 3);

        assert_eq!(
            root3,
            block_on(client.local.fetch_metadata::<RootMetadata>(
                &MetadataPath::from_role(&Role::Root),
                &MetadataVersion::Number(3),
                &None,
                None
            ))
            .unwrap(),
        );
    }
}
