#include <libregexis024sol/expr_parse_functions/tracking_units.h>
#include <libregexis024sol/sol_misc_base.h>

#define aux_THROW(str) do { report(ctx, "regex: " str); return; } while (0)
#define aux_ERROR_CHECK do { if (ctx.error) { return; } } while (0)

namespace regexis024 {
    void for_one_type(REGEX_IS024_MeaningContext &ctx, uint16_t& free_ARR_tai, int& ARR_first, int& ARR_second,
                      const std::string& ARR_NAME, tracking_var_type_t type){
#define check_is_available() if (free_ARR_tai == UINT16_MAX) { \
report(ctx, ("regex: " + ARR_NAME + ": key namespace overflow").c_str()); return;}
        check_is_available()
        ARR_first = free_ARR_tai++;
        if (type == tracking_var_types::range){
            check_is_available()
            ARR_second = free_ARR_tai++;
        }
    }

    void ensure_space_for_track_unit(REGEX_IS024_MeaningContext &ctx, const std::string& name, tracking_var_type_t type) {
        size_t id = ctx.ktr.track_names[name];
        /* Size of this verctor won't be changed. THis is a safe reference */
        SubtrackingNameUsageInfo& info = ctx.ktr.retrieval_info[id];
        if (!info.discovered){
            info.type = type;
            if (info.stored_in_ca) {
                for_one_type(ctx, ctx.free_colarr_tai, info.colarr_first, info.colarr_second, "collection array", type);
                aux_ERROR_CHECK;
            }
            if (info.stored_in_sa) {
                for_one_type(ctx, ctx.free_selarr_tai, info.selarr_first, info.selarr_second, "selection array", type);
                aux_ERROR_CHECK;
            }
            info.discovered = true;
        } else if (info.type != type){
            aux_THROW("tracking tool unit type mismatch");
        }
    }
}