use anyhow::Result;
use env_logger::Env;

// use the library crate modules
use snippets::{cli, engine, serve, watch};

fn main() -> Result<()> {
    let cfg = cli::parse_args()?;

    // Initialize logging based on verbosity
    let default_level = if cfg.verbose { "debug" } else { "info" };
    env_logger::Builder::from_env(Env::default().default_filter_or(default_level)).init();

    // make it mutable so we can call full_build(&mut self)
    let mut engine = engine::Engine::new(
        cfg.src_dir.clone(),
        cfg.out_dir.clone(),
        cfg.snippets_dir.clone(),
        cfg.content_dir.clone(),
        cfg.static_dir.clone(),
        cfg.verbose,
    )?;

    if cfg.watch {
        // High-level build message in watch mode
        eprintln!(
            "Building {} to {} (run with --verbose for more details)",
            cfg.src_dir.display(),
            cfg.out_dir.display()
        );

        // Start a static server on localhost at the chosen port
        let port = cfg.port;
        let _server = serve::start_static_server(cfg.out_dir.clone(), port, cfg.verbose)
            .map_err(|e| anyhow::anyhow!("failed to start server on 127.0.0.1:{}: {}", port, e))?;
        eprintln!("Local server: http://127.0.0.1:{}/", port);

        // move the engine into the watcher (run_watch takes Engine by value)
        watch::run_watch(engine)
    } else {
        // High-level build message in normal (non-watch) mode with hint
        eprintln!(
            "Building {} to {} (run with --verbose for more details; run with --watch to run in watch mode)",
            cfg.src_dir.display(),
            cfg.out_dir.display()
        );

        // use it mutably here
        engine.full_build()
    }
}
