#ifndef PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_VERY_BASE_H
#define PROTOTYPE1_SRC_L1_ANNE_UTIL_TEMP_VERY_BASE_H

#include "../codegen/util_template_inst.h"

/* These headers are guarded */
void generate_util_temp_very_base_headers() {
    SpanU8 l = cstr("l1"), ns = cstr("");
    SpanU8 T_codegen_VecAndSpan[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("S32"), cstr("U64"), cstr("S64")};
    SpanU8 T_codegen_Option[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64"), cstr("S64")};
    SpanU8 T_codegen_VecAndSpan_of_Vec[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};
    SpanU8 T_codegen_VecAndSpan_of_Span[] = {cstr("U8"), cstr("U16"), cstr("U32"), cstr("U64")};
    for (size_t i = 0; i < ARRAY_SIZE(T_codegen_VecAndSpan); i++) {
        generate_util_templ_inst_guarded_header(l, ns,
            cstr(""),
            (util_templates_instantiation_options){
            .T = T_codegen_VecAndSpan[i],
            .t_integer = true, .t_primitive = true, .vec = true, .vec_extended = true,
            .vec_equal = true, .span = true, .span_extended = true, .mut_span = true,
            .collab_vec_span = true, .collab_vec_span_extended = true,
        });
    }
    for (size_t i = 0; i < ARRAY_SIZE(T_codegen_Option); i++) {
        generate_Option_templ_inst_guarded_header(l, ns,
            cstr(""),
            (option_template_instantiation_op){.T = T_codegen_Option[i], .t_integer = true});
    }
    for (size_t i = 0; i < ARRAY_SIZE(T_codegen_VecAndSpan_of_Vec); i++) {
        VecU8 VecT = VecU8_fmt("Vec%s", T_codegen_VecAndSpan_of_Vec[i]);
        VecU8 dependency = VecU8_fmt("#include \"VecAndSpan_%s.h\"", T_codegen_VecAndSpan_of_Vec[i]);
        generate_util_templ_inst_guarded_header(l, ns,
            VecU8_to_span(&dependency),
            (util_templates_instantiation_options){
            .T = VecU8_to_span(&VecT), .t_clonable = true, .vec = true, .vec_extended = true,
            .span = true, .collab_vec_span = true, .vec_equal = true, .vec_new_of_size = true
        });
        VecU8_drop(VecT);
        VecU8_drop(dependency);
    }
    for (size_t i = 0; i < ARRAY_SIZE(T_codegen_VecAndSpan_of_Span); i++) {
        VecU8 SpanT = VecU8_fmt("Span%s", T_codegen_VecAndSpan_of_Span[i]);
        VecU8 dependency = VecU8_fmt("#include \"VecAndSpan_%s.h\"", T_codegen_VecAndSpan_of_Span[i]);
        generate_util_templ_inst_guarded_header(l, ns,
            VecU8_to_span(&dependency),
            (util_templates_instantiation_options){
            .T = VecU8_to_span(&SpanT), .t_primitive = true, .vec = true, .span = true, .mut_span = true, .collab_vec_span = true,
        });
        VecU8_drop(SpanT);
        VecU8_drop(dependency);
    }
    generate_guarded_span_company_for_primitive(l, ns, cstr("CSTR"), cstr(""), true, false);

    generate_ResultType_templ_inst_guarded_header(l, ns,
        cstr(""), cstr("VecU8"), cstr("#include \"VecAndSpan_U8.h\""), true, false);
    generate_ResultType_templ_inst_guarded_header(l, ns,
        cstr(""), cstr("SpanU8"), cstr("#include \"VecAndSpan_U8.h\""), true, true);

    generate_guarded_span_company_for_primitive(l, ns, cstr("U32Segment"),
        cstr("#include \"../../src/l1/core/uint_segments.h\""), true, true);

    /* Not very basic but definitely very common */
    generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8G8B8A8"),
        cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false);
    generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8G8B8"),
     cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false);
    generate_guarded_span_company_for_non_primitive_clonable(l, ns, cstr("TextureDataR8"),
     cstr("#include \"../../gen/l1/pixel_masses.h\"\n"), true, false);

    generate_guarded_span_company_for_primitive(l, ns, cstr("KVPU64ToU64"), cstr(""), true, false);
}

#endif