#![warn(unused_extern_crates)]
use std::fs;

#[cfg(feature = "profile")]
use cpuprofiler::PROFILER;
use log::info;
use stderrlog;
use structopt::StructOpt;

use renderer::renderer::render;
use renderer::renderer::Opt;

#[cfg(not(feature = "profile"))]
struct MockTimer;

#[cfg(not(feature = "profile"))]
impl MockTimer {
    fn start<T: Into<Vec<u8>>>(&self, _: T) -> Result<(), ()> {
        Ok(())
    }
    fn stop(&self) -> Result<(), ()> {
        Ok(())
    }
}

#[cfg(not(feature = "profile"))]
struct MockProfiler;

#[cfg(not(feature = "profile"))]
impl MockProfiler {
    fn lock(&self) -> Option<MockTimer> {
        Some(MockTimer {})
    }
}

#[cfg(not(feature = "profile"))]
static PROFILER: MockProfiler = MockProfiler {};

fn main() -> Result<(), std::io::Error> {
    stderrlog::new()
        .verbosity(3)
        .timestamp(stderrlog::Timestamp::Millisecond)
        .init()
        .unwrap();
    let opt = Opt::from_args();
    info!("{:?}", opt);
    let scene = opt.model.scene(&opt);
    fs::create_dir_all(&opt.output)?;
    if opt.pprof.is_some() && !cfg!(feature = "profile") {
        panic!("profiling disabled at compile time, but -pprof specified");
    }
    if let Some(ref pprof_path) = opt.pprof {
        PROFILER
            .lock()
            .unwrap()
            .start(pprof_path.to_str().unwrap().as_bytes())
            .unwrap();
    }
    let res = render(scene, &opt.output);
    if let Some(pprof_path) = &opt.pprof {
        info!("Saving pprof to {}", pprof_path.to_string_lossy());
        PROFILER.lock().unwrap().stop().unwrap();
    }

    res
}
