use std::net::TcpStream;
use std::io::prelude::*;
use std::thread;
use std::sync::{Arc, Mutex, RwLock};

use crate::protocol;

pub struct Client<'a>{
    client: Arc<Mutex<TcpStream>>,
    server:Arc<Mutex<TcpStream>>,
    //client: &'static TcpStream,
    //server: &'static TcpStream,
    hs: protocol::HandShake<'a>,
    run : Arc<RwLock<bool>>,
    //run: &'static bool
}

impl<'a> Client<'a> {
    pub fn new(client: TcpStream, server: TcpStream, handshake: protocol::HandShake) -> Client{
        Client {
            client: Arc::new(Mutex::new(client)),
            server: Arc::new(Mutex::new(server)),
            //client: client,
            //server: server,
            hs: handshake,
            run: Arc::new(RwLock::new(true)),
            //run: &true,
        }
    }

    pub fn to_string(&self){
        println!("len_pack {}", self.hs.getHostName());
    }
    
    //pub get_hostname(buf &mod)

    fn join_conexions_mutex(c1: Arc<Mutex<TcpStream>>,
            c2: Arc<Mutex<TcpStream>>,
            run: Arc<RwLock<bool>>,
            id: i32){
        let mut buf: [u8; 1000000] = [0; 1000000];
        let mut client = c1.lock().unwrap().try_clone().unwrap();
        while *run.read().unwrap() {
            println!("read{}",id);
            let res=client.read(&mut buf);
            match res {
                Ok(leng) => {
                    println!("rx {}",leng);
                    if leng == 0 {
                        *run.write().unwrap()=false;
                    }
                    println!("tx {}",c2.lock().unwrap().write(&buf [.. leng]).unwrap());
                },
                //Ok(leng) => {c2.lock().unwrap().write(&buf);},
                Err(_e) => {*run.write().unwrap()=false;},
            }
            println!("write{}",id);

        }
    }

    pub fn start_proxy(&self) -> (thread::JoinHandle<()>, thread::JoinHandle<()>) {

        //let c = client.client;
        let c1 = self.client.clone();
        let s1 = self.server.clone();
        let r1 = self.run.clone();
        let handler1 = thread::spawn( || {
            Self::join_conexions_mutex(s1,
                c1,
                r1,1)}
        );

        let c2 = self.client.clone();
        let s2 = self.server.clone();
        let r2 = self.run.clone();
        let handler2 = thread::spawn( || {
            Self::join_conexions_mutex(c2,
                s2,
                r2,2)}
        );

        return (handler1, handler2);
        /*let handler = thread::spawn( || {
            Self::join_conexions(&mut client.client,
                &mut client.server,
                &mut client.run)}
        );

        let handler2 = thread::spawn( || {
            Self::join_conexions(&mut client.client,
                &mut client.server,
                &mut client.run)}
        );*/
    }
}
