use std::sync::atomic::AtomicU64;
use std::sync::Arc;

use example::client::SimpleTestService;
use example::JRPCClient;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::TcpStream;
use tokio::sync::mpsc::channel;

#[tokio::main]
pub async fn main() {
    let (tx, mut rx) = channel(1);
    let stream = TcpStream::connect("127.0.0.1:4321").await.unwrap();
    let client = example::JRPCClient::new(tx.clone());
    let test_service = SimpleTestService::new(client.clone());

    let (reader, mut writer) = stream.into_split();
    let mut reader = BufReader::new(reader);
    let mut line = String::new();

    tokio::spawn(async move {
        loop {
            line.clear();
            reader.read_line(&mut line).await.unwrap();
            client.on_result(serde_json::from_str(&line).unwrap()).await;
        }
    });

    tokio::spawn(async move {
        while let Some(message) = rx.recv().await {
            writer
                .write_all((serde_json::to_string(&message).unwrap() + "\n").as_bytes())
                .await
                .unwrap();
        }
    });

    let ticks = Arc::new(AtomicU64::new(0));
    let t2 = ticks.clone();
    tokio::spawn(async move {
        loop {
            tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
            println!("Ticks: {}", t2.load(std::sync::atomic::Ordering::Relaxed));
            t2.store(0, std::sync::atomic::Ordering::Relaxed);
        }
    });

    loop {
        let _result = test_service.GetTest("Hi".to_owned(), 55).await.unwrap();
        ticks.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
    }
}
