use crate::{get_test_file, split_last_delimited_char};
use anyhow::Context;
use std::io::Write;

pub fn generate_escaped_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("escaped_tests.rs")?;

    for (line, number) in include_str!("../resources/tests/parsers/char/escaped/valid.txt").lines().enumerate() {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/escaped/template.txt"),
            case = format!("{:03}", line),
            number = number
        )
        .context(format!("failed to write test escaped::case_{}", line))?;
    }

    Ok(())
}

pub fn generate_mark_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("mark_tests.rs")?;

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/mark/valid.csv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/mark/template.txt"),
            name = name,
            symbol = symbol
        )
        .context(format!("failed to write test mark::{}", name))?;
    }

    Ok(())
}

pub fn generate_p_char_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("p_char_tests.rs")?;

    for letter in ('a'..='z').chain('A'..='Z') {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/p_char/template.txt"),
            case = letter,
            char = letter
        )
        .context(format!("failed to write test p_char::case_{}", letter))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/mark/valid.csv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/p_char/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test p_char::case_{}", name))?;
    }

    for (line, number) in include_str!("../resources/tests/parsers/char/escaped/valid.txt").lines().enumerate() {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/p_char/template.txt"),
            case = format!("{:03}", line),
            char = number
        )
        .context(format!("failed to write test p_char::case_{}", line))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/p_char/valid.tsv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/p_char/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test p_char::{}", name))?;
    }

    Ok(())
}

pub fn generate_reserved_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("reserved_tests.rs")?;

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/reserved/valid.tsv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/reserved/template.txt"),
            name = name,
            symbol = symbol
        )
        .context(format!("failed to write test reserved::{}", name))?;
    }

    Ok(())
}

pub fn generate_unreserved_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("unreserved_tests.rs")?;

    for letter in ('a'..='z').chain('A'..='Z') {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/unreserved/template.txt"),
            name = letter,
            symbol = letter
        )
        .context(format!("failed to write test unreserved::{}", letter))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/mark/valid.csv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/unreserved/template.txt"),
            name = name,
            symbol = symbol
        )
        .context(format!("failed to write test unreserved::{}", name))?;
    }

    Ok(())
}

pub fn generate_uri_c_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("uri_c_tests.rs")?;

    for letter in ('a'..='z').chain('A'..='Z') {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c/template.txt"),
            case = letter,
            char = letter
        )
        .context(format!("failed to write test uri_c::case_{}", letter))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/mark/valid.csv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test uri_c::case_{}", name))?;
    }

    for (line, number) in include_str!("../resources/tests/parsers/char/escaped/valid.txt").lines().enumerate() {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c/template.txt"),
            case = format!("{:03}", line),
            char = number
        )
        .context(format!("failed to write test uri_c::case_{}", line))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/reserved/valid.tsv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test uri_c::{}", name))?;
    }

    Ok(())
}

pub fn generate_uri_c_no_slash_tests() -> anyhow::Result<()> {
    let mut test_file = get_test_file("uri_c_no_slash_tests.rs")?;

    for letter in ('a'..='z').chain('A'..='Z') {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c_no_slash/template.txt"),
            case = letter,
            char = letter
        )
        .context(format!("failed to write test uri_c_no_slash::case_{}", letter))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/mark/valid.csv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c_no_slash/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test uri_c_no_slash::case_{}", name))?;
    }

    for (line, number) in include_str!("../resources/tests/parsers/char/escaped/valid.txt").lines().enumerate() {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c_no_slash/template.txt"),
            case = format!("{:03}", line),
            char = number
        )
        .context(format!("failed to write test uri_c_no_slash::case_{}", line))?;
    }

    for (name, symbol) in
        include_str!("../resources/tests/parsers/char/uri_c_no_slash/valid.tsv").lines().map(split_last_delimited_char)
    {
        write!(
            test_file,
            include_str!("../resources/tests/parsers/char/uri_c_no_slash/template.txt"),
            case = name,
            char = symbol
        )
        .context(format!("failed to write test uri_c_no_slash::{}", name))?;
    }

    Ok(())
}
