extern crate chrono;
#[macro_use]
extern crate maplit;
extern crate tuf;

use chrono::prelude::*;
use chrono::offset::Utc;
use tuf::Error;
use tuf::client::{Client, Config};
use tuf::crypto::{PrivateKey, SignatureScheme, KeyId, HashAlgorithm};
use tuf::interchange::{DataInterchange, JsonDataInterchange};
use tuf::metadata::{RoleDefinition, RootMetadata, Role, MetadataVersion, MetadataPath,
                    SignedMetadata, TargetDescription, TargetPath, TargetsMetadata,
                    MetadataDescription, SnapshotMetadata, TimestampMetadata};
use tuf::repository::{EphemeralRepository, Repository};

// Ironically, this is far from simple, but it's as simple as it can be made.

const ED25519_1_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-1.pk8.der");
const ED25519_2_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-2.pk8.der");
const ED25519_3_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-3.pk8.der");
const ED25519_4_PK8: &'static [u8] = include_bytes!("./ed25519/ed25519-4.pk8.der");

#[test]
fn main() {
    let mut remote = EphemeralRepository::<JsonDataInterchange>::new();
    let root_key_ids = init_server(&mut remote).unwrap();
    init_client(&root_key_ids, remote).unwrap();
}

fn init_client(
    root_key_ids: &[KeyId],
    remote: EphemeralRepository<JsonDataInterchange>,
) -> Result<(), Error> {
    let local = EphemeralRepository::<JsonDataInterchange>::new();
    let config = Config::build().finish()?;

    let mut client = Client::with_root_pinned(root_key_ids, config, local, remote)?;
    match client.update_local() {
        Ok(_) => (),
        Err(e) => println!("{:?}", e),
    }
    let _ = client.update_remote()?;
    client.fetch_target(&TargetPath::new("grendel".into())?)
}

fn init_server(remote: &mut EphemeralRepository<JsonDataInterchange>) -> Result<Vec<KeyId>, Error> {
    // in real life, you wouldn't want these keys on the same machine ever
    let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8)?;
    let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8)?;
    let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8)?;
    let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8)?;

    //// build the root ////

    let keys = vec![
        root_key.public().clone(),
        snapshot_key.public().clone(),
        targets_key.public().clone(),
        timestamp_key.public().clone(),
    ];

    let root_def = RoleDefinition::new(1, hashset!(root_key.key_id().clone()))?;
    let snapshot_def = RoleDefinition::new(1, hashset!(snapshot_key.key_id().clone()))?;
    let targets_def = RoleDefinition::new(1, hashset!(targets_key.key_id().clone()))?;
    let timestamp_def = RoleDefinition::new(1, hashset!(timestamp_key.key_id().clone()))?;

    let root = RootMetadata::new(
        1,
        Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
        false,
        keys,
        root_def,
        snapshot_def,
        targets_def,
        timestamp_def,
    )?;

    let signed = SignedMetadata::<JsonDataInterchange, RootMetadata>::new(
        &root,
        &root_key,
        SignatureScheme::Ed25519,
    )?;

    remote.store_metadata(
        &Role::Root,
        &MetadataPath::new("root".into())?,
        &MetadataVersion::Number(1),
        &signed,
    )?;
    remote.store_metadata(
        &Role::Root,
        &MetadataPath::new("root".into())?,
        &MetadataVersion::None,
        &signed,
    )?;

    //// build the targets ////

    let target_file: &[u8] = b"things fade, alternatives exclude";
    let target_path = TargetPath::new("grendel".into())?;
    let target_description = TargetDescription::from_reader(target_file, &[HashAlgorithm::Sha256])?;
    let _ = remote.store_target(target_file, &target_path);

    let target_map = hashmap!(target_path => target_description);
    let targets = TargetsMetadata::new(1, Utc.ymd(2038, 1, 1).and_hms(0, 0, 0), target_map, None)?;

    let signed = SignedMetadata::<JsonDataInterchange, TargetsMetadata>::new(
        &targets,
        &targets_key,
        SignatureScheme::Ed25519,
    )?;

    remote.store_metadata(
        &Role::Targets,
        &MetadataPath::new("targets".into())?,
        &MetadataVersion::Number(1),
        &signed,
    )?;
    remote.store_metadata(
        &Role::Targets,
        &MetadataPath::new("targets".into())?,
        &MetadataVersion::None,
        &signed,
    )?;

    let targets_bytes =
        JsonDataInterchange::canonicalize(&JsonDataInterchange::serialize(&signed)?)?;

    //// build the snapshot ////
    let meta_map =
        hashmap! {
        MetadataPath::new("targets".into())? =>
            MetadataDescription::from_reader(&*targets_bytes, 1, &[HashAlgorithm::Sha256])?,
    };
    let snapshot = SnapshotMetadata::new(1, Utc.ymd(2038, 1, 1).and_hms(0, 0, 0), meta_map)?;

    let signed = SignedMetadata::<JsonDataInterchange, SnapshotMetadata>::new(
        &snapshot,
        &snapshot_key,
        SignatureScheme::Ed25519,
    )?;

    remote.store_metadata(
        &Role::Snapshot,
        &MetadataPath::new("snapshot".into())?,
        &MetadataVersion::Number(1),
        &signed,
    )?;
    remote.store_metadata(
        &Role::Snapshot,
        &MetadataPath::new("snapshot".into())?,
        &MetadataVersion::None,
        &signed,
    )?;

    let snapshot_bytes =
        JsonDataInterchange::canonicalize(&JsonDataInterchange::serialize(&signed)?)?;

    //// build the timestamp ////
    let snap = MetadataDescription::from_reader(&*snapshot_bytes, 1, &[HashAlgorithm::Sha256])?;
    let timestamp = TimestampMetadata::new(1, Utc.ymd(2038, 1, 1).and_hms(0, 0, 0), snap)?;

    let signed = SignedMetadata::<JsonDataInterchange, TimestampMetadata>::new(
        &timestamp,
        &timestamp_key,
        SignatureScheme::Ed25519,
    )?;

    remote.store_metadata(
        &Role::Timestamp,
        &MetadataPath::new("timestamp".into())?,
        &MetadataVersion::Number(1),
        &signed,
    )?;
    remote.store_metadata(
        &Role::Timestamp,
        &MetadataPath::new("timestamp".into())?,
        &MetadataVersion::None,
        &signed,
    )?;

    Ok(vec![root_key.key_id().clone()])
}
