use ed25519_dalek::SecretKey;
use rand::rngs::OsRng;
use tapir_cwtch::acns::tor::authentication::HashedPassword;
use tapir_cwtch::acns::tor::TorProcess;
use tapir_cwtch::applications::authentication_app::{AuthenicationApp, AUTHENTICATION_CAPABILITY};
use tapir_cwtch::connections::service::Service;
use tapir_cwtch::connections::{Connection, ConnectionInterface, OutboundConnection};
use tapir_cwtch::primitives::identity::Identity;
use tapir_cwtch::primitives::transcript::Transcript;

fn main() {
    let mut auth_control_port = TorProcess::connect(9051)
        .unwrap()
        .authenticate(Box::new(HashedPassword::new(String::from("examplehashedpassword"))))
        .unwrap();
    let mut csprng = OsRng {};
    let keypair = ed25519_dalek::Keypair::generate(&mut csprng);
    match auth_control_port.add_onion_v3(SecretKey::from_bytes(&keypair.secret.to_bytes()).unwrap(), 9878, 10029) {
        Ok(service_id) => {
            // we authenticated!
            let identity = Identity::initialize(keypair);
            println!("Service Id: {}", service_id);
            println!("Setup: {}", identity.hostname());

            let mut service = Service::init(identity.clone());

            let identity = identity.clone();
            let outbound_identity = identity.clone();
            let outbound_service = |conn: Connection<OutboundConnection>| {
                let mut transcript = Transcript::new_transcript("tapir-transcript");
                let mut auth_app = AuthenicationApp::new(outbound_identity);
                match auth_app.run_outbound(conn, &mut transcript) {
                    Ok(conn) => {
                        println!("Authenticated {} {}", conn.hostname(), conn.has_capability(&AUTHENTICATION_CAPABILITY));
                    }
                    Err(err) => {
                        println!("Error: {:?}", err);
                    }
                }
            };
            match service.connect("hvdl5hckss4od2bn7zm2ho6ybak3heopfvxkbx6li3yl7avzc52aluid", outbound_service.clone()) {
                _ => {}
            }
            loop {}
        }
        Err(err) => println!("{:?}", err),
    }
}
