use dbui_controllers::routes::add_routes;
use dbui_service::AppConfig;

use actix_service::Service;
use actix_session::CookieSession;
use actix_web::{App, HttpServer};
use futures::future::Future;
use std::time::SystemTime;

pub(crate) fn start_server(cfg: AppConfig) -> std::io::Result<()> {
  let server_cfg = cfg.clone();

  let server = HttpServer::new(move || {
    App::new()
      .data(server_cfg.clone())
      .wrap(
        CookieSession::signed(&[0; 32])
          .http_only(true)
          .name(dbui_core::APPNAME)
          .secure(false)
      )
      .wrap(actix_web::middleware::Compress::default())
      .wrap_fn(|req, srv| {
        let p = req.path().to_owned();
        let start_time = SystemTime::now();
        let cfg: AppConfig = match req.app_data::<AppConfig>() {
          Some(ad) => ad.get_ref().to_owned(),
          None => panic!("Missing AppConfig data reference!")
        };
        let useful = !p.starts_with("/static");
        if useful {
          slog::trace!(cfg.root_logger(), "Request received for path [{}]", p);
        }
        srv.call(req).map(move |res| {
          if useful {
            let elapsed_time = SystemTime::now()
              .duration_since(start_time)
              .ok()
              .map(|x| x.as_micros() as f64)
              .get_or_insert(0f64)
              .to_owned();
            let ms = elapsed_time / 1000.0;
            slog::debug!(
              cfg.root_logger(), "{}", res.response().status();
              "path" => &p, "status" => format!("{}", res.response().status().as_u16()), "elapsed" => format!("{}", ms)
            );
          }
          res
        })
      })
      .configure(|s| add_routes(s))
  });

  let msg = format!("[dbui] started, open http://{}:{} to get going!", cfg.address(), cfg.port());
  slog::info!(cfg.root_logger(), "{}", msg);

  match server.bind(format!("{}:{}", &cfg.address(), cfg.port())) {
    Ok(s) => s.run(),
    Err(e) => {
      slog::info!(cfg.root_logger(), "Error starting server: {:?}", e);
      Err(e)
    }
  }
}
