use std::env;
use std::fs::File;
use std::io::Write;
use std::path::Path;

use walkdir::WalkDir;

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let destination = Path::new(&out_dir).join("tests.rs");
    let mut test_file = File::create(&destination).unwrap();

    write_header(&mut test_file);

    let test_files = WalkDir::new("org_mode_samples")
        .into_iter()
        .filter(|e| match e {
            Ok(dir_entry) => {
                dir_entry.file_type().is_file()
                    && Path::new(dir_entry.file_name())
                        .extension()
                        .map(|ext| ext.to_ascii_lowercase() == "org")
                        .unwrap_or(false)
            }
            Err(_) => true,
        })
        .collect::<Result<Vec<_>, _>>()
        .unwrap();
    for test in test_files {
        write_test(&mut test_file, &test);
    }
}

fn write_test(test_file: &mut File, test: &walkdir::DirEntry) {
    let test_name = test
        .path()
        .strip_prefix("org_mode_samples/")
        .expect("Paths should be under org_mode_samples/")
        .to_string_lossy()
        .to_lowercase()
        .strip_suffix(".org")
        .expect("Should have .org extension")
        .replace("/", "_");

    if let Some(_reason) = is_expect_fail(test_name.as_str()) {
        write!(test_file, "#[ignore]\n").unwrap();
    }
    write!(
        test_file,
        include_str!("./tests/test_template"),
        name = test_name,
        path = test.path().display()
    )
    .unwrap();
}

fn write_header(test_file: &mut File) {
    write!(
        test_file,
        r#"
#[feature(exit_status_error)]
use organic::compare_document;
use organic::parser::document;
use organic::emacs_parse_org_document;
use organic::parser::sexp::sexp_with_padding;

"#
    )
    .unwrap();
}

fn is_expect_fail(name: &str) -> Option<&str> {
    match name {
        "drawer_drawer_with_headline_inside" => Some("Apparently lines with :end: become their own paragraph. This odd behavior needs to be investigated more."),
        "element_container_priority_footnote_definition_dynamic_block" => Some("Apparently broken begin lines become their own paragraph."),
        "element_container_priority_drawer_greater_block" => Some("Need to implement subscript."),
        "element_container_priority_dynamic_block_greater_block" => Some("Need to implement subscript."),
        "element_container_priority_footnote_definition_greater_block" => Some("Need to implement subscript."),
        "element_container_priority_greater_block_greater_block" => Some("Need to implement subscript."),
        "element_container_priority_section_greater_block" => Some("Need to implement subscript."),
        "paragraphs_paragraph_with_backslash_line_breaks" => Some("The text we're getting out of the parse tree is already processed to remove line breaks, so our comparison needs to take that into account."),
        "export_snippet_paragraph_break_precedent" => Some("Emacs 28 has broken behavior so the tests in the CI fail."),
        _ => None,
    }
}