Documentation
// Copyright 2022 Parthka. All rights reserved. MIT license.

mod main_handler;
mod req_body;
mod request;
mod response;
mod router;
mod types;

pub use hyper::Method;
pub use req_body::read_response_body;
pub use request::Req;
pub use response::Res;
pub use router::Router;
pub use types::{HandFn, Headers, Route};
use main_handler::main_handler;
use hyper::service::{make_service_fn, service_fn};
use hyper::Server;
use std::convert::Infallible;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};

// web server
pub struct WebServer {
    port: u16,
    router: Router,
}

impl WebServer {
    pub fn new() -> Self {
        WebServer {
            port: 8080,
            router: Router { routes: Vec::new() },
        }
    }

    pub fn set_port(&mut self, port: u16) {
        self.port = port
    }

    pub fn set_router(&mut self, router: Router) {
        self.router = router
    }

    async fn listen(&mut self) {
        // main address
        let addr = SocketAddr::from(([0, 0, 0, 0], self.port));

        // make server service
        let make_svc = make_service_fn(|_conn| {
            let r = Arc::new(Mutex::new(self.router.clone()));
            async move {
                //
                Ok::<_, Infallible>(service_fn(move |req| main_handler(req, r.clone())))
            }
        });

        // bind to add
        let server = Server::bind(&addr).serve(make_svc);

        // server listen
        if let Err(e) = server.await {
            eprintln!("server error: {}", e);
        }
    }

    pub fn run(&mut self) {
        // make tokio runtime
        tokio::runtime::Builder::new_multi_thread()
            .enable_all()
            .build()
            .unwrap()
            .block_on(async {
                // call server listen function
                self.listen().await
            });
    }
}