//! Test data.
//!
//! This module includes the test data from `keystore/tests/data` in a
//! structured way.

use std::fmt;
use std::collections::BTreeMap;
use std::path::PathBuf;

use lazy_static::lazy_static;

use sequoia_openpgp as openpgp;
use openpgp::Fingerprint;

pub struct Test {
    path: &'static str,
    pub bytes: &'static [u8],
}

impl fmt::Display for Test {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "keystore/tests/data/{}", self.path)
    }
}

pub fn dir() -> PathBuf {
    PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/data"))
}

/// Returns the content of the given file below `keystore/tests/data`.
pub fn file(name: &str) -> &'static [u8] {
    lazy_static::lazy_static! {
        static ref FILES: BTreeMap<&'static str, &'static [u8]> = {
            let mut m: BTreeMap<&'static str, &'static [u8]> =
                Default::default();

            macro_rules! add {
                ( $key: expr, $path: expr ) => {
                    m.insert($key, include_bytes!($path))
                }
            }
            include!(concat!(env!("OUT_DIR"), "/tests.index.rs.inc"));

            // Sanity checks.
            assert!(m.contains_key("simple/dave.pgp"));
            m
        };
    }

    FILES.get(name).unwrap_or_else(|| panic!("No such file {:?}", name))
}


pub struct EncryptedMessage {
    pub filename: &'static str,
    pub recipients: Vec<&'static Fingerprint>,
    pub content: &'static str,
}

macro_rules! em {
    ( $dir:expr, $name:expr $(, $recip:ident)* ) => {
        EncryptedMessage {
            filename: concat!($dir, "/", $name, ".pgp"),
            recipients: vec![ $(&*$recip,)* ],
            content: concat!($name, "\n"),
        }
    }
}

#[allow(non_upper_case_globals)]
pub mod simple {
    use super::*;

    // The encryption subkeys.
    lazy_static! {
        pub static ref alice: Fingerprint
            = "EBB7CD5ED3AF234A0AD15BDA1B19948D7A8424A4".parse().unwrap();
        pub static ref alice_pri: Fingerprint
            = "AE81192975C08CA56C257BD3A29F4223DDD881B2".parse().unwrap();
        pub static ref bob: Fingerprint
            = "92D7E5A2005676E7F2B350B11DF3BDD1D6072B44".parse().unwrap();
        pub static ref carol: Fingerprint
            = "AF2620370975120E25A0469FAC13CAA7E282324B".parse().unwrap();
        pub static ref carol_pri: Fingerprint
            = "CD6C4799E67CC4A551B7F2F400431FF5B8A682CD".parse().unwrap();

        pub static ref MSGS: [EncryptedMessage; 13] = [
            em!("simple", "for-alice", alice),
            em!("simple", "for-bob", bob),
            em!("simple", "for-carol", carol),
            em!("simple", "for-dave"),
            em!("simple", "for-alice-bob", alice, bob),
            em!("simple", "for-alice-carol", alice, carol),
            em!("simple", "for-alice-dave", alice),
            em!("simple", "for-bob-alice", bob, alice),
            em!("simple", "for-carol-alice", carol, alice),
            em!("simple", "for-carol-dave", carol),
            em!("simple", "for-dave-alice", alice),
            em!("simple", "for-dave-carol", carol),
            em!("simple", "for-dave-alice-bob-carol", alice, bob, carol),
        ];
    }

    pub fn dir() -> PathBuf {
        super::dir().join("simple")
    }
}

#[allow(non_upper_case_globals)]
pub mod password {
    use super::*;

    // The encryption subkeys.
    lazy_static! {
        pub static ref alice_pri: Fingerprint
            = "B9D905221577435EC69E6C10F9DF67187D2BF8B2".parse().unwrap();
        pub static ref alice: Fingerprint
            = "9B980721629F4A98332438635AE7278072A2D0D2".parse().unwrap();
        pub static ref bob_pri: Fingerprint
            = "7E0622ECF641D2FFE9A47C854A04BA480CE3E102".parse().unwrap();
        pub static ref bob: Fingerprint
            = "568078BB9A65285B8A7B4498E3B63B9AE4D10DD5".parse().unwrap();
        pub static ref frank_pri: Fingerprint
            = "D7347AEF97CCAF209FCC4DBBFEB42E3C9D46ED92".parse().unwrap();
        pub static ref frank: Fingerprint
            = "9FB98AB6ADEBCCD0D11943258738B7C8950072AE".parse().unwrap();

        // The string is the password needed to decrypt the message.
        //
        // - Alice: unencrypted.
        // - Bob: two variants: unencrypted and encrypted.
        // - Frank: encrypted.
        pub static ref MSGS: [(EncryptedMessage, Option<&'static str>); 6] = [
            (em!("password", "for-alice-bob", alice, bob), None),
            (em!("password", "for-bob-alice", bob, alice), None),
            (em!("password", "for-bob", bob), None),
            (em!("password", "for-frank", frank), Some("foo")),
            (em!("password", "for-frank-bob", frank, bob), None),
            (em!("password", "for-frank-bob", frank, bob), None),
        ];
    }

    pub fn dir() -> PathBuf {
        super::dir().join("password")
    }
}
