#![warn(clippy::todo, clippy::unimplemented)]
use std::{io::{Read, Result as IoResult, Write}, net::{IpAddr, TcpStream}, sync::Arc};

use postgresql_client::{PsqlSession, Location};

use uri::Host;
use http::{Response, parse::parse_response, Header, Request, RequestTarget};

fn main() {
    println!("Hello, world!");
    let psql_session = PsqlSession::connect(None).unwrap();
}

fn todostuff() {
    todo!()
}

//WIP: Tear apart and reconfigure structure.
fn fetch_resource_http(host: Host, path: String) -> Result<Response, String> {
    let request = Request {
        method: http::Method::Get,
        version: http::HttpVersion::Http11,
        target: RequestTarget::Origin(path),
        headers: vec![Header::Host(host.clone())],
        body: vec![],
    };

    //Connect to a host.
    
    let mut connection = TcpStream::connect((match host {
        Host::Ip(ip_addr) => ip_addr,
        Host::Name(domain) => dns::lookup_via_system(domain).unwrap()[0],
    }, 443)).unwrap();

    // Negotiate a TLS connection.
    
    let root_store = rustls::RootCertStore::from_iter(
        webpki_roots::TLS_SERVER_ROOTS
            .iter()
            .cloned(),
    );
    
    let config = rustls::ClientConfig::builder()
        .with_root_certificates(root_store)
        .with_no_client_auth();
    
    let rc_config = Arc::new(config);
    let example_com = "example.com".try_into().unwrap();
    let mut client = rustls::ClientConnection::new(rc_config, example_com).unwrap();

    //Get the writer

    let mut writer = client.writer();

    // Start sending data

    request.write_to(&mut writer).unwrap();

    loop {
        let mut buf = vec!();
        if client.wants_read() && connection.peek(&mut buf).is_ok() {
            client.read_tls(&mut connection).unwrap();
            client.process_new_packets().unwrap();

            let mut plaintext = vec!();
            client.reader().read_to_end(&mut plaintext).unwrap();

            match parse_response(&plaintext) {
                Ok(Some(r)) => return Ok(r), //We have a complete response.
                Ok(None) => continue, // We need more bytes, keep reading. 
                Err(e) => panic!(), // Some error, return.
            };
        }
    }
}