//! Clients for high level interactions with TUF repositories.
//!
//! # Example
//!
//! ```no_run
//! #![feature(async_await, await_macro, futures_api, pin)]
//! # 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, HttpRepository};
//!
//! 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 = HttpRepository::new(
//!     url::Url::parse("https://static.rust-lang.org/").unwrap(),
//!     HttpClient::new(),
//!     Some("rustup/1.4.0".into()),
//!     None);
//!
//! 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;

/// 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,
            config.min_bytes_per_second,
            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,
            config.min_bytes_per_second,
            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,
                    config.min_bytes_per_second,
                    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,
            self.config.min_bytes_per_second,
            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,
                self.config.min_bytes_per_second,
                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,
            self.config.min_bytes_per_second,
            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,
            self.config.min_bytes_per_second,
            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,
            self.config.min_bytes_per_second,
            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,
            self.config.min_bytes_per_second,
        ))
    }

    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,
                self.config.min_bytes_per_second(),
                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,
                        self.config.min_bytes_per_second(),
                        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::pinned(self.lookup_target_description(
                        delegation.terminating(),
                        current_depth + 1,
                        target,
                        snapshot,
                        Some(meta.as_ref()),
                    )));

                    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.min_bytes_per_second(), 4096);
/// 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>,
    min_bytes_per_second: u32,
    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 minimum bytes per second for a read to be considered good.
    pub fn min_bytes_per_second(&self) -> u32 {
        self.min_bytes_per_second
    }

    /// 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),
            min_bytes_per_second: 4096,
            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>,
    min_bytes_per_second: u32,
    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,
            min_bytes_per_second: self.min_bytes_per_second,
            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 minimum bytes per second for a read to be considered good.
    pub fn min_bytes_per_second(mut self, min: u32) -> Self {
        self.min_bytes_per_second = min;
        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,
            min_bytes_per_second: self.min_bytes_per_second,
            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,
            min_bytes_per_second: cfg.min_bytes_per_second,
            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;
    use std::u32;

    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,
                u32::MAX,
                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,
                u32::MAX,
                None
            ))
            .unwrap(),
        );
    }
}
