#![warn(unused_extern_crates)]
#![allow(non_snake_case)]


use std::{env, thread};

use diesel::{r2d2::{self, ConnectionManager}, SqliteConnection};
use dotenvy::dotenv;
use ntex_files as fs;
use ntex::web;

mod api;
mod proxy;
mod db;
mod models;
mod providers;
mod schema;
mod status;
mod util;
mod videos;
mod proxies;

type DbPool = r2d2::Pool<ConnectionManager<SqliteConnection>>;

// #[macro_use(c)]
// extern crate cute;


#[ntex::main]
async fn main() -> std::io::Result<()> {
    // std::env::set_var("RUST_BACKTRACE", "1");
    dotenv().ok();

    // Enable request logging
    if std::env::var("RUST_LOG").is_err() {
        unsafe{
            std::env::set_var("RUST_LOG", "warn");
        }
    }
    env_logger::init(); // You need this to actually see logs

    // set up database connection pool
    let connspec = std::env::var("DATABASE_URL").expect("DATABASE_URL");
    let manager = ConnectionManager::<SqliteConnection>::new(connspec.clone());
    let pool = r2d2::Pool::builder()
        .build(manager)
        .expect("Failed to create pool.");

    let mut requester = util::requester::Requester::new();
    requester.set_proxy(env::var("PROXY").unwrap_or("0".to_string()) != "0".to_string());

    let cache: util::cache::VideoCache = crate::util::cache::VideoCache::new().max_size(100_000).to_owned();
    
    thread::spawn(move || {
            // Create a tiny runtime just for these async tasks
            let rt = tokio::runtime::Builder::new_current_thread()
                .enable_all()
                .build()
                .expect("build tokio runtime");

            rt.block_on(async move {
                providers::init_providers_now(); 
            });
        });
    
    web::HttpServer::new(move || {
        web::App::new()
            .state(pool.clone())
            .state(cache.clone())
            .state(requester.clone())
            .wrap(web::middleware::Logger::default())
            .service(web::scope("/api").configure(api::config))
            .service(web::scope("/proxy").configure(proxy::config))
            .service(
            web::resource("/")
                .route(web::get().to(|req: web::HttpRequest| async move{
                let host = match std::env::var("DOMAIN"){
                    Ok(d) => d,
                    Err(_) => req.connection_info().host().to_string()
                };
                let source_forward_header = format!("hottub://source?url={}", host);
                web::HttpResponse::Found()
                    .header("Location", source_forward_header)
                    .finish()
                }))
            )
            .service(fs::Files::new("/", "static").index_file("index.html"))
    })
    .workers(8)
    // .bind_openssl(("0.0.0.0", 18080), builder)?
    .bind(("0.0.0.0", 18080))?
    .run()
    .await
}
