mod app;
mod cookie;
mod middleware;
mod service;
mod static_files;
mod testing;
mod tls_config;
mod website;
use actix_files::Files;
use actix_web::{web, App, HttpServer};
use actix_web_lab::middleware::RedirectHttps;
use app::{AppArgs, AppState};
use middleware::AuthService;
use static_files::StaticFilesManager;
use std::sync::RwLock;
use structopt::StructOpt;
use tls_config::tls_config;
use website::WebSiteBuilder;

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let app_state = AppState::builder().use_args(AppArgs::from_args()).build();

    env_logger::Builder::from_env(
        env_logger::Env::default().default_filter_or(&app_state.config.get_log_level()),
    )
    .init();

    let website = WebSiteBuilder::load(&app_state.config)
        .with_static_files_manager(
            StaticFilesManager::new(&app_state)
                .unwrap()
                .build_assets_index(),
        )
        .build()
        .unwrap();

    website.save(&app_state.config).unwrap();

    let host = app_state.config.host.clone();
    let port = app_state.config.port;
    let port_tls = app_state.config.port_tls;

    let srv_conf = tls_config(&app_state.config);
    let dir = website.static_files_manager.dir.clone();

    HttpServer::new(move || {
        App::new()
            .wrap(actix_web::middleware::Logger::default())
            .wrap(actix_web::middleware::Compress::default())
            .wrap(RedirectHttps::default().to_port(port_tls))
            .app_data(web::Data::new(RwLock::new(app_state.clone())))
            .app_data(web::Data::new(RwLock::new(website.clone())))
            .service(
                web::scope("/admin")
                    .service(service::admin_login)
                    .service(service::admin_authenticate)
                    .service(
                        web::scope("/auth")
                            .wrap(AuthService {})
                            .service(service::admin_workspace)
                            .service(service::add_page)
                            .service(service::get_page_data)
                            .service(service::update_page)
                            .service(service::files::post_files)
                            .service(service::files::delete_static_file)
                            .service(service::add_template)
                            .service(service::update_template)
                            .service(service::remove_page)
                            .service(service::remove_template),
                    ),
            )
            .service(service::files::favicon)
            .service(Files::new("/", &dir).index_file("index.html"))
    })
    .bind(format!("{}:{}", host, port))?
    .bind_rustls(format!("{}:{}", host, port_tls), srv_conf)?
    .run()
    .await
}