use std::convert::TryInto;

use bech32::{ToBase32, Variant};
use ed25519_dalek::{Keypair, PublicKey as EdPublicKey, Signature, Signer, Verifier};
use rand::rngs::OsRng;
use x25519_dalek::{EphemeralSecret, PublicKey};

fn main() {
    let mut csprng = OsRng {};
    let keypair = Keypair::generate(&mut csprng);
    println!("Key pair: {:#?}", keypair);

    let message = b"This is sign test message.";
    let signature = keypair.sign(message);
    println!("Signature: {}", hex::encode(signature));

    let public_key = keypair.public;
    println!("Verify result: {:?}", public_key.verify(message, &signature));

    // key exchange
    println!("{}", "-".repeat(88));
    let alice_secret = EphemeralSecret::new(OsRng);
    let alice_public = PublicKey::from(&alice_secret);
    let bob_secret = EphemeralSecret::new(OsRng);
    let bob_public = PublicKey::from(&bob_secret);

    let alice_shared_secret = alice_secret.diffie_hellman(&bob_public);
    let bob_shared_secret = bob_secret.diffie_hellman(&alice_public);

    println!("Alice public key   : {}", hex::encode(alice_public.as_bytes()));
    println!("Bob   public key   : {}", hex::encode(bob_public.as_bytes()));

    println!("Alice shared secret: {}", hex::encode(alice_shared_secret.as_bytes()));
    println!("Bob   shared secret: {}", hex::encode(bob_shared_secret.as_bytes()));

    println!("{}", "-".repeat(88));
    let public_key_bytes = hex::decode("7FEBAAB0D80CED24730B613F3D86924560EBCF13A838DEBC065F63C69C24C61E").unwrap();
    let public_key_bytes: [u8; 32] = public_key_bytes.try_into().unwrap();
    let public_key_card = PublicKey::from(public_key_bytes);
    println!("Public key card: {}", hex::encode(public_key_card.as_bytes()));
    let age_addr = bech32::encode(
        "age",
        public_key_card.as_bytes().to_base32(),
        Variant::Bech32,
    ).unwrap();
    println!("Public key card as age address: {}", age_addr);

    let new_secret = EphemeralSecret::new(OsRng);
    let new_public = PublicKey::from(&new_secret);
    println!("New public key: {}", hex::encode(new_public.as_bytes()));
    let new_card_shared_secret = new_secret.diffie_hellman(&public_key_card);
    println!("New&card shared secret: {}", hex::encode(new_card_shared_secret.as_bytes()));

    println!("{}", "-".repeat(88));
    // $ cargo r -- pgp-card-sign -2 1dc91001cb69b0dbfab0347d684d7551227484f57a5ac414680414b855051159 --algo eddsa
    // [OK   ] User sign pin verify success!
    // [OK   ] SHA256 signature HEX: 4b2355918b92ca8e5490a30775aa4603a76efe344e3eecfd888b10018a5cb86d3d7095c298b34b39c4e1d46841098dd2514101a9eba5b7a271cf9b5c9d078306
    let public_key_bytes = hex::decode("d57a081448c6d3d6076b1cca0216f319e45cc2ad986541caf0d3d62f5b318263").unwrap();
    let public_key_card = EdPublicKey::from_bytes(&public_key_bytes).unwrap();
    let message = hex::decode("1dc91001cb69b0dbfab0347d684d7551227484f57a5ac414680414b855051159").unwrap();
    let signature = hex::decode("4b2355918b92ca8e5490a30775aa4603a76efe344e3eecfd888b10018a5cb86d3d7095c298b34b39c4e1d46841098dd2514101a9eba5b7a271cf9b5c9d078306").unwrap();
    let signature_bytes: [u8; 64] = signature.try_into().unwrap();
    let signature = Signature::new(signature_bytes);
    let verify_result = public_key_card.verify(&message, &signature);
    println!("Verify result: {:?}", verify_result);
}
