use std::path::PathBuf;

use http::handling::{
    file_handlers::NamedFile,
    methods::Method,
    request::Request,
    response::{Outcome, Response, ResponseBody, Status},
    routes::{Data, Route},
};

fn handle_static_hi(request: Request<'_>, data: Data) -> Outcome<Response, Status, Data> {
    // Outcome::Success(Response { headers: vec![
    //     format!("Content-Length: 4"), 
    //     format!("Content-Type: text/plain")
    // ], status: Some(Status::Ok), body: Box::new("jkl;") })
    Outcome::Forward(data)
}


fn handler(request: Request<'_>, _data: Data) -> Outcome<Response, Status, Data> {
    let response = fileserver(request.uri.strip_prefix("static/").unwrap());
    let response = match response {
        Ok(dat) => Response {
            headers: vec![
                format!("Content-Length: {}", dat.get_len()),
                format!("Content-Type: {}", dat.get_mime()),
            ],
            status: Some(Status::Ok),
            body: Box::new(dat),
        },
        Err(_) => return Outcome::Failure(Status::NotFound),
    };
    Outcome::Success(response)
}

fn fileserver(path: &str) -> Result<NamedFile, Status> {
    NamedFile::open(PathBuf::from("static/".to_string() + path))
}

fn post_hi_handler(_request: Request, data: Data) -> Outcome<Response, Status, Data> {
    if data.is_empty() {
        return Outcome::Forward(data);
    }
    let data = if let Ok(str) = String::from_utf8(data.buffer) {
        str
    } else {
        return Outcome::Failure(Status::BadRequest);
    };
    let dat = post_hi(data);
    Outcome::Success(Response {
        headers: vec![
            format!("Content-Length: {}", dat.len()),
            format!("Content-Type: text/plain"),
        ],
        status: Some(Status::Ok),
        body: Box::new(dat),
    })
}

fn post_hi(msg: String) -> String {
    msg
}

#[tokio::main]
async fn main() {
    let fileserver = Route {
        format: None,
        handler,
        name: Some("file_server"),
        uri: "static/<path..>",
        method: Method::Get,
        rank: 1,
    };

    let post_test = Route {
        format: None,
        handler: post_hi_handler,
        name: Some("post_test"),
        uri: "post",
        method: Method::Post,
        rank: 0,
    };

    let static_hi = Route {
        format: None, 
        handler: handle_static_hi,
        name: Some("Handle_Static_hi"),
        uri: "static/hi",
        method: Method::Get,
        rank: 0
    };

    http::build("127.0.0.1:8000").await
        .mount("/", vec![fileserver, post_test, static_hi])
        .launch().await;
}