use std::{io, collections::HashMap, env::args, os::unix::fs::MetadataExt};
use bytes::BytesMut;
use tokio::{net::{TcpListener, TcpStream}, io::{AsyncReadExt, AsyncWriteExt}, fs::File};


use itertools::Itertools;
use nom::AsChar;

#[derive(Debug)]
enum BodyTypes {
    File(File),
    String(String)
}

async fn process_socket(mut stream: TcpStream) -> Result<(), &'static str> {
    println!("accepted new connection");
    let mut request: HashMap<String, String> = HashMap::new();
    let mut line_num: usize = 0;
    loop {
        let mut line = String::default();

        loop {
            let mut buf: [u8; 1] = [0; 1];
            stream.read_exact(&mut buf).await.unwrap();

            let character = buf[0].as_char();
            if character == '\n' {
                break
            } else if character != '\r' {
                line.push(character);
            }
        }

        if line_num == 0 {
            let mut splits = line.split(' ');
            request.insert("method".to_owned(), splits.next().unwrap().to_owned());
            request.insert("path".to_owned(), splits.next().unwrap().to_owned());
        } else {
            let mut splits = line.split(":");
            let key = splits.next().unwrap();
            let value = splits.next().unwrap_or_default().trim();
            request.insert(key.to_owned(), value.to_owned());
        }

        if request.get("path").unwrap() != "/user-agent" || request.contains_key("User-Agent") { break };
        line_num += 1;
    }

    let mut path = request.get("path").unwrap().split("/");

    let response_status: String;
    let mut response_headers: Vec<String> = vec![];
    let response_body: BodyTypes;

    path.next().unwrap();

    match path.next().unwrap() {
        "" => {
            response_status = "200 OK".into();
            response_body = BodyTypes::String("".into());
        },
        "echo" => {
            response_status = "200 OK".into();
            response_body = BodyTypes::String(path.join("/"));
            response_headers.push("Content-Type: text/plain".into());
        },
        "user-agent" => {
            response_status = "200 OK".into();
            response_body = BodyTypes::String(request.get("User-Agent").unwrap().into());
            response_headers.push("Content-Type: text/plain".into());
        },
        "files" => {
            let file_name = path.join("/");
            let args: Vec<String> = args().collect();
            let dir_arg = args.iter().find_position(|item| **item == "--directory");
            let file_path = if dir_arg.is_some() {
                args[dir_arg.unwrap().0+1].to_owned() + "/" + file_name.as_str()
            } else {
                return Err("No directory Given".into())
            };
            let maybe_file = File::open(file_path).await;

            match maybe_file {
                Ok(file) => {
                    response_status = "200 OK".into();
                    response_body = BodyTypes::File(file);
                    response_headers.push("Content-Type: application/octet-stream".into());
                },
                Err(_) => {
                    response_status = "404 Not Found".into();
                    response_body = BodyTypes::String("".into());
                }
            }
        },
        _ => {
            response_status = "404 Not Found".into();
            response_body = BodyTypes::String("".into());
        }
    }

    println!("{:?}", response_body);

    match response_body {
        BodyTypes::String(ref content) => {
            if content.len() > 0 {
                response_headers.push(format!("Content-Length: {}", content.len()));
            };
        },
        BodyTypes::File(ref file) => {
            response_headers.push(format!("Content-Length: {}", file.metadata().await.unwrap().size()));
        }
    }

    stream.write(format!("HTTP/1.1 {response_status}\r\n{}\r\n\r\n", response_headers.join("\r\n")).as_bytes()).await.unwrap();

    match response_body {
        BodyTypes::String(ref content) => {
            stream.write(content.as_bytes()).await.unwrap();
        },
        BodyTypes::File(mut file) => {
            loop {
                let mut buf = BytesMut::with_capacity(1024);

                let read = file.read_buf(&mut buf).await.unwrap();

                if read == 0 {
                    break;
                }

                stream.write(&mut buf).await.unwrap();
            }
        }
    }

    Ok(())
}

#[tokio::main]
async fn main() -> io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:4221").await?;
    let mut futures = vec![];

    loop {
        let (socket, _) = listener.accept().await?;
        futures.push(tokio::spawn(process_socket(socket)));
    }
}
