//! 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, 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;

/// 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::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.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(),
        );
    }
}
