#include "../runtime/slop_runtime.h"
#include "slop_growl.h"

rdf_Term growl_remap_blank_term(slop_arena* arena, rdf_Term t, int64_t offset);
int64_t growl_max_blank_id_in_graph(index_IndexedGraph ig);
types_ReasonerConfig growl_default_config(void);
types_ReasonerResult growl_reason(slop_arena* arena, index_IndexedGraph input);
types_ReasonerResult growl_reason_with_config(slop_arena* arena, index_IndexedGraph input, types_ReasonerConfig config);
uint8_t growl_is_consistent(slop_arena* arena, index_IndexedGraph input);
slop_list_rdf_Term growl_get_types(slop_arena* arena, index_IndexedGraph g, rdf_Term individual);
slop_list_rdf_Term growl_get_same_as(slop_arena* arena, index_IndexedGraph g, rdf_Term individual);
int64_t growl_get_inferred_count(types_ReasonerResult result);

rdf_Term growl_remap_blank_term(slop_arena* arena, rdf_Term t, int64_t offset) {
    __auto_type _mv_308 = t;
    switch (_mv_308.tag) {
        case rdf_Term_term_blank:
        {
            __auto_type b = _mv_308.data.term_blank;
            return rdf_make_blank(arena, (b.id + offset));
        }
        case rdf_Term_term_iri:
        {
            __auto_type _ = _mv_308.data.term_iri;
            return t;
        }
        case rdf_Term_term_literal:
        {
            __auto_type _ = _mv_308.data.term_literal;
            return t;
        }
    }
}

int64_t growl_max_blank_id_in_graph(index_IndexedGraph ig) {
    {
        __auto_type triples = ig.triples;
        int64_t max_id = 0;
        {
            __auto_type _coll = triples;
            for (size_t _i = 0; _i < _coll.len; _i++) {
                __auto_type t = _coll.data[_i];
                __auto_type _mv_309 = t.subject;
                switch (_mv_309.tag) {
                    case rdf_Term_term_blank:
                    {
                        __auto_type b = _mv_309.data.term_blank;
                        if (b.id > max_id) {
                            max_id = b.id;
                        }
                        break;
                    }
                    default: {
                        break;
                    }
                }
                __auto_type _mv_310 = t.object;
                switch (_mv_310.tag) {
                    case rdf_Term_term_blank:
                    {
                        __auto_type b = _mv_310.data.term_blank;
                        if (b.id > max_id) {
                            max_id = b.id;
                        }
                        break;
                    }
                    default: {
                        break;
                    }
                }
            }
        }
        return max_id;
    }
}

types_ReasonerConfig growl_default_config(void) {
    types_ReasonerConfig _retval = {0};
    _retval = ((types_ReasonerConfig){.worker_count = 4, .channel_buffer = 256, .max_iterations = 1000, .verbose = 1, .fast = 0, .complete = 0, .enrich = 0, .validate = 0, .validate_ns = SLOP_STR(""), .cancel_ptr = 0, .max_triples = 0});
    SLOP_POST(((_retval.worker_count == 4)), "(== (. $result worker-count) 4)");
    SLOP_POST(((_retval.channel_buffer == 256)), "(== (. $result channel-buffer) 256)");
    SLOP_POST(((_retval.max_iterations == 1000)), "(== (. $result max-iterations) 1000)");
    SLOP_POST(((_retval.verbose == 1)), "(== (. $result verbose) true)");
    SLOP_POST(((_retval.fast == 0)), "(== (. $result fast) false)");
    SLOP_POST(((_retval.complete == 0)), "(== (. $result complete) false)");
    SLOP_POST(((_retval.enrich == 0)), "(== (. $result enrich) false)");
    SLOP_POST(((_retval.validate == 0)), "(== (. $result validate) false)");
    SLOP_POST(((_retval.max_triples == 0)), "(== (. $result max-triples) 0)");
    return _retval;
}

types_ReasonerResult growl_reason(slop_arena* arena, index_IndexedGraph input) {
    SLOP_PRE(((rdf_indexed_graph_size(input) >= 0)), "(>= (indexed-graph-size input) 0)");
    types_ReasonerResult _retval = {0};
    _retval = growl_reason_with_config(arena, input, growl_default_config());
    SLOP_POST((({ __auto_type _mv = _retval; uint8_t _mr = {0}; switch (_mv.tag) { case types_ReasonerResult_reason_success: { __auto_type s = _mv.data.reason_success; _mr = (s.inferred_count >= 0); break; } case types_ReasonerResult_reason_inconsistent: { __auto_type _ = _mv.data.reason_inconsistent; _mr = 1; break; } case types_ReasonerResult_reason_cancelled: { __auto_type s = _mv.data.reason_cancelled; _mr = (s.inferred_count >= 0); break; }  } _mr; })), "(match $result ((reason-success s) (>= (. s inferred-count) 0)) ((reason-inconsistent _) true) ((reason-cancelled s) (>= (. s inferred-count) 0)))");
    return _retval;
}

types_ReasonerResult growl_reason_with_config(slop_arena* arena, index_IndexedGraph input, types_ReasonerConfig config) {
    SLOP_PRE(((rdf_indexed_graph_size(input) >= 0)), "(>= (indexed-graph-size input) 0)");
    SLOP_PRE(((config.worker_count >= 1)), "(>= (. config worker-count) 1)");
    SLOP_PRE(((config.max_iterations >= 1)), "(>= (. config max-iterations) 1)");
    types_ReasonerResult _retval = {0};
    _retval = engine_engine_run(arena, config, input);
    SLOP_POST((({ __auto_type _mv = _retval; uint8_t _mr = {0}; switch (_mv.tag) { case types_ReasonerResult_reason_success: { __auto_type s = _mv.data.reason_success; _mr = (s.iterations <= config.max_iterations); break; } case types_ReasonerResult_reason_inconsistent: { __auto_type _ = _mv.data.reason_inconsistent; _mr = 1; break; } case types_ReasonerResult_reason_cancelled: { __auto_type s = _mv.data.reason_cancelled; _mr = (s.iterations <= config.max_iterations); break; }  } _mr; })), "(match $result ((reason-success s) (<= (. s iterations) (. config max-iterations))) ((reason-inconsistent _) true) ((reason-cancelled s) (<= (. s iterations) (. config max-iterations))))");
    return _retval;
}

uint8_t growl_is_consistent(slop_arena* arena, index_IndexedGraph input) {
    SLOP_PRE(((rdf_indexed_graph_size(input) >= 0)), "(>= (indexed-graph-size input) 0)");
    __auto_type _mv_311 = growl_reason(arena, input);
    switch (_mv_311.tag) {
        case types_ReasonerResult_reason_success:
        {
            __auto_type _ = _mv_311.data.reason_success;
            return 1;
        }
        case types_ReasonerResult_reason_inconsistent:
        {
            __auto_type _ = _mv_311.data.reason_inconsistent;
            return 0;
        }
        case types_ReasonerResult_reason_cancelled:
        {
            __auto_type _ = _mv_311.data.reason_cancelled;
            return 1;
        }
    }
}

slop_list_rdf_Term growl_get_types(slop_arena* arena, index_IndexedGraph g, rdf_Term individual) {
    SLOP_PRE(((rdf_indexed_graph_size(g) >= 0)), "(>= (indexed-graph-size g) 0)");
    slop_list_rdf_Term _retval = {0};
    {
        __auto_type type_pred = rdf_make_iri(arena, vocab_RDF_TYPE);
        slop_option_rdf_Term no_term = (slop_option_rdf_Term){.has_value = false};
        __auto_type matches = rdf_indexed_graph_match(arena, g, (slop_option_rdf_Term){.has_value = 1, .value = individual}, (slop_option_rdf_Term){.has_value = 1, .value = type_pred}, no_term);
        __auto_type result = ((slop_list_rdf_Term){ .data = (rdf_Term*)slop_arena_alloc(arena, 16 * sizeof(rdf_Term)), .len = 0, .cap = 16 });
        {
            __auto_type _coll = matches;
            for (size_t _i = 0; _i < _coll.len; _i++) {
                __auto_type t = _coll.data[_i];
                ({ __auto_type _lst_p = &(result); __auto_type _item = (t.object); if (_lst_p->len >= _lst_p->cap) { size_t _new_cap = _lst_p->cap == 0 ? 16 : _lst_p->cap * 2; __typeof__(_lst_p->data) _new_data = (__typeof__(_lst_p->data))slop_arena_alloc(arena, _new_cap * sizeof(*_lst_p->data)); if (_lst_p->len > 0) memcpy(_new_data, _lst_p->data, _lst_p->len * sizeof(*_lst_p->data)); _lst_p->data = _new_data; _lst_p->cap = _new_cap; } _lst_p->data[_lst_p->len++] = _item; (void)0; });
            }
        }
        _retval = result;
    }
    SLOP_POST(((((int64_t)((_retval).len)) >= 0)), "(>= (list-len $result) 0)");
    return _retval;
}

slop_list_rdf_Term growl_get_same_as(slop_arena* arena, index_IndexedGraph g, rdf_Term individual) {
    SLOP_PRE(((rdf_indexed_graph_size(g) >= 0)), "(>= (indexed-graph-size g) 0)");
    slop_list_rdf_Term _retval = {0};
    {
        __auto_type same_pred = rdf_make_iri(arena, vocab_OWL_SAME_AS);
        slop_option_rdf_Term no_term = (slop_option_rdf_Term){.has_value = false};
        __auto_type as_subject = rdf_indexed_graph_match(arena, g, (slop_option_rdf_Term){.has_value = 1, .value = individual}, (slop_option_rdf_Term){.has_value = 1, .value = same_pred}, no_term);
        __auto_type as_object = rdf_indexed_graph_match(arena, g, no_term, (slop_option_rdf_Term){.has_value = 1, .value = same_pred}, (slop_option_rdf_Term){.has_value = 1, .value = individual});
        __auto_type result = ((slop_list_rdf_Term){ .data = (rdf_Term*)slop_arena_alloc(arena, 16 * sizeof(rdf_Term)), .len = 0, .cap = 16 });
        ({ __auto_type _lst_p = &(result); __auto_type _item = (individual); if (_lst_p->len >= _lst_p->cap) { size_t _new_cap = _lst_p->cap == 0 ? 16 : _lst_p->cap * 2; __typeof__(_lst_p->data) _new_data = (__typeof__(_lst_p->data))slop_arena_alloc(arena, _new_cap * sizeof(*_lst_p->data)); if (_lst_p->len > 0) memcpy(_new_data, _lst_p->data, _lst_p->len * sizeof(*_lst_p->data)); _lst_p->data = _new_data; _lst_p->cap = _new_cap; } _lst_p->data[_lst_p->len++] = _item; (void)0; });
        {
            __auto_type _coll = as_subject;
            for (size_t _i = 0; _i < _coll.len; _i++) {
                __auto_type t = _coll.data[_i];
                ({ __auto_type _lst_p = &(result); __auto_type _item = (t.object); if (_lst_p->len >= _lst_p->cap) { size_t _new_cap = _lst_p->cap == 0 ? 16 : _lst_p->cap * 2; __typeof__(_lst_p->data) _new_data = (__typeof__(_lst_p->data))slop_arena_alloc(arena, _new_cap * sizeof(*_lst_p->data)); if (_lst_p->len > 0) memcpy(_new_data, _lst_p->data, _lst_p->len * sizeof(*_lst_p->data)); _lst_p->data = _new_data; _lst_p->cap = _new_cap; } _lst_p->data[_lst_p->len++] = _item; (void)0; });
            }
        }
        {
            __auto_type _coll = as_object;
            for (size_t _i = 0; _i < _coll.len; _i++) {
                __auto_type t = _coll.data[_i];
                ({ __auto_type _lst_p = &(result); __auto_type _item = (t.subject); if (_lst_p->len >= _lst_p->cap) { size_t _new_cap = _lst_p->cap == 0 ? 16 : _lst_p->cap * 2; __typeof__(_lst_p->data) _new_data = (__typeof__(_lst_p->data))slop_arena_alloc(arena, _new_cap * sizeof(*_lst_p->data)); if (_lst_p->len > 0) memcpy(_new_data, _lst_p->data, _lst_p->len * sizeof(*_lst_p->data)); _lst_p->data = _new_data; _lst_p->cap = _new_cap; } _lst_p->data[_lst_p->len++] = _item; (void)0; });
            }
        }
        _retval = result;
    }
    SLOP_POST(((((int64_t)((_retval).len)) >= 0)), "(>= (list-len $result) 0)");
    return _retval;
}

int64_t growl_get_inferred_count(types_ReasonerResult result) {
    int64_t _retval = {0};
    __auto_type _mv_312 = result;
    switch (_mv_312.tag) {
        case types_ReasonerResult_reason_success:
        {
            __auto_type s = _mv_312.data.reason_success;
            return s.inferred_count;
        }
        case types_ReasonerResult_reason_inconsistent:
        {
            __auto_type _ = _mv_312.data.reason_inconsistent;
            return 0;
        }
        case types_ReasonerResult_reason_cancelled:
        {
            __auto_type s = _mv_312.data.reason_cancelled;
            return s.inferred_count;
        }
    }
    SLOP_POST(((_retval >= 0)), "(>= $result 0)");
    return _retval;
}

