use anyhow::*;
use clap::Parser;
use env_logger::Env;
use log::*;

use crate::{options::ServerOptions, server::run_server};

mod cdn;
mod fixups;
mod logging;
mod manifest;
mod options;
mod redirect;
mod server;
mod server_info;
mod site;

/// Opinionated web server
#[derive(Debug, Clone, Parser)]
#[command(name = "opserve", version)]
struct ServerCLI {
    /// Check and pretty-print a manifest.
    #[arg(short = 'C', long = "check-manifest")]
    check_manifest: bool,

    #[command(flatten)]
    options: ServerOptions,
}

fn main() -> Result<()> {
    setup_logging();
    let cli = ServerCLI::parse();
    debug!("command line: {:#?}", cli);
    let cli: &'static ServerCLI = Box::leak(Box::new(cli));

    if cli.check_manifest {
        let path = cli.options.manifest_path();
        let manifest = if path.exists() {
            info!("checking manifest at {}", path.display());
            manifest::load_manifest(&path)?
        } else {
            warn!(
                "manifest {} does not exist, synthesizing from root",
                path.display()
            );
            manifest::generate_manifest(&cli.options.content_root)?
        };
        println!("{}", serde_json::to_string_pretty(&manifest)?);
        return Ok(());
    }

    run_server(&cli.options)
}

fn setup_logging() {
    let env = Env::default()
        .filter_or("OPSERVE_LOG", "info")
        .write_style("OPSERVE_LOG_STYLE");
    env_logger::Builder::from_env(env).init();
}
