#include <luna/String.h>
#include <test.h>

TestResult test_no_format()
{
    auto fmt = TRY(String::format("Hello, world!"_sv));

    validate(fmt.view() == "Hello, world!");

    test_success;
}

TestResult test_basic_string_format()
{
    auto fmt = TRY(String::format("%s"_sv, "Hello, world!"));

    validate(fmt.view() == "Hello, world!");

    test_success;
}

TestResult test_string_format_with_extra_chars()
{
    auto fmt = TRY(String::format("Hello, %s!"_sv, "world"));

    validate(fmt.view() == "Hello, world!");

    test_success;
}

TestResult test_string_format_with_width()
{
    auto fmt = TRY(String::format("Hello,%6s!"_sv, "world"));

    validate(fmt.view() == "Hello, world!");

    test_success;
}

TestResult test_string_format_left_align()
{
    auto fmt = TRY(String::format("Hello, %-7s"_sv, "world!"));

    validate(fmt.view() == "Hello, world! ");

    test_success;
}

TestResult test_string_format_precision()
{
    auto fmt = TRY(String::format("Hello, %.5s!"_sv, "world! this is some extra stuff we don't need"));

    validate(fmt.view() == "Hello, world!");

    test_success;
}

TestResult test_basic_signed_integer_format()
{
    auto fmt = TRY(String::format("%d"_sv, 42));

    validate(fmt.view() == "42");

    test_success;
}

TestResult test_negative_signed_integer_format()
{
    auto fmt = TRY(String::format("%d"_sv, -653));

    validate(fmt.view() == "-653");

    test_success;
}

TestResult test_positive_signed_integer_format()
{
    auto fmt = TRY(String::format("%+d"_sv, 653));

    validate(fmt.view() == "+653");

    test_success;
}

TestResult test_positive_signed_integer_format_with_empty_sign()
{
    auto fmt = TRY(String::format("% d"_sv, 653));

    validate(fmt.view() == " 653");

    test_success;
}

TestResult test_format_zero_with_explicit_zero_precision()
{
    auto fmt = TRY(String::format("%.0d"_sv, 0));

    validate(fmt.is_empty());

    test_success;
}

TestResult test_octal_format()
{
    auto fmt = TRY(String::format("%o"_sv, 34));

    validate(fmt.view() == "42");

    test_success;
}

TestResult test_hex_format()
{
    auto fmt = TRY(String::format("%x"_sv, 43707));

    validate(fmt.view() == "aabb");

    test_success;
}

TestResult test_uppercase_hex_format()
{
    auto fmt = TRY(String::format("%X"_sv, 43707));

    validate(fmt.view() == "AABB");

    test_success;
}

TestResult test_integer_format_with_width()
{
    auto fmt = TRY(String::format("%6d"_sv, 42));

    validate(fmt.view() == "    42");

    test_success;
}

TestResult test_zero_padded_integer_format_with_width()
{
    auto fmt = TRY(String::format("%06d"_sv, 42));

    validate(fmt.view() == "000042");

    test_success;
}

TestResult test_integer_format_with_precision()
{
    auto fmt = TRY(String::format("%.6d"_sv, 42));

    validate(fmt.view() == "000042");

    test_success;
}

TestResult test_alternate_integer_format_with_width()
{
    auto fmt = TRY(String::format("%#6x"_sv, 66));

    validate(fmt.view() == "  0x42");

    test_success;
}

TestResult test_zero_padded_alternate_integer_format_with_width()
{
    auto fmt = TRY(String::format("%0#6x"_sv, 66));

    validate(fmt.view() == "0x0042");

    test_success;
}

TestResult test_alternate_integer_format_with_precision()
{
    auto fmt = TRY(String::format("%#.6x"_sv, 66));

    validate(fmt.view() == "0x000042");

    test_success;
}

TestResult test_integer_format_left_align()
{
    auto fmt = TRY(String::format("%-6d"_sv, 42));

    validate(fmt.view() == "42    ");

    test_success;
}

TestResult test_integer_format_left_align_override_zero_pad()
{
    auto fmt = TRY(String::format("%-06d"_sv, 42));

    validate(fmt.view() == "42    ");

    test_success;
}

TestResult test_integer_format_left_align_with_alternate_format()
{
    auto fmt = TRY(String::format("%#-6o"_sv, 0755));

    validate(fmt.view() == "0755  ");

    test_success;
}

TestResult test_integer_format_left_align_with_alternate_format_and_precision()
{
    auto fmt = TRY(String::format("%#-8.5x"_sv, 0x44bb));

    validate(fmt.view() == "0x044bb ");

    test_success;
}

TestResult test_va_integer_width()
{
    auto fmt = TRY(String::format("%0*d"_sv, 4, 42));

    validate(fmt.view() == "0042");

    test_success;
}

TestResult test_va_integer_precision()
{
    auto fmt = TRY(String::format("%0.*d"_sv, 4, 42));

    validate(fmt.view() == "0042");

    test_success;
}

TestResult test_no_precision_assumed_as_zero()
{
    auto fmt = TRY(String::format("%.d"_sv, 42));

    validate(fmt.view() == "42");

    test_success;
}

TestResult test_no_precision_assumed_as_explicit_zero()
{
    auto fmt = TRY(String::format("%.d"_sv, 0));

    validate(fmt.view() == "");

    test_success;
}

TestResult test_negative_va_width()
{
    auto fmt = TRY(String::format("%*d"_sv, -4, 42));

    validate(fmt.view() == "42  ");

    test_success;
}

TestResult test_negative_va_precision()
{
    auto fmt = TRY(String::format("%.*d"_sv, -6, 0));

    validate(fmt.view() == "0");

    test_success;
}

TestResult test_verbatim_percent_format()
{
    auto fmt = TRY(String::format("%%"_sv));

    validate(fmt.view() == "%");

    test_success;
}

TestResult test_format_character()
{
    auto fmt = TRY(String::format("exampl%c"_sv, 'e'));

    validate(fmt.view() == "example");

    test_success;
}

Result<void> test_main()
{
    test_prelude;

    run_test(test_no_format);
    run_test(test_basic_string_format);
    run_test(test_string_format_with_extra_chars);
    run_test(test_string_format_with_width);
    run_test(test_string_format_left_align);
    run_test(test_string_format_precision);
    run_test(test_basic_signed_integer_format);
    run_test(test_negative_signed_integer_format);
    run_test(test_positive_signed_integer_format);
    run_test(test_positive_signed_integer_format_with_empty_sign);
    run_test(test_format_zero_with_explicit_zero_precision);
    run_test(test_octal_format);
    run_test(test_hex_format);
    run_test(test_uppercase_hex_format);
    run_test(test_integer_format_with_width);
    run_test(test_zero_padded_integer_format_with_width);
    run_test(test_integer_format_with_precision);
    run_test(test_alternate_integer_format_with_width);
    run_test(test_zero_padded_alternate_integer_format_with_width);
    run_test(test_alternate_integer_format_with_precision);
    run_test(test_integer_format_left_align);
    run_test(test_integer_format_left_align_override_zero_pad);
    run_test(test_integer_format_left_align_with_alternate_format);
    run_test(test_integer_format_left_align_with_alternate_format_and_precision);
    run_test(test_va_integer_width);
    run_test(test_va_integer_precision);
    run_test(test_no_precision_assumed_as_zero);
    run_test(test_no_precision_assumed_as_explicit_zero);
    run_test(test_negative_va_width);
    run_test(test_negative_va_precision);
    run_test(test_verbatim_percent_format);
    run_test(test_format_character);

    return {};
}