#include <time.h>
#include "lsup_rdf.h"

#define NT 100000

static LSUP_Triple *
generate_triples(size_t nt)
{
    LSUP_Triple *trp;
    trp = malloc((nt  + 1) * sizeof(LSUP_Triple));
    if (!trp) exit (-1);

    for (size_t i = 0; i < nt; i++) {
        char sstr[32], pstr[32], ostr[32];

        sprintf(sstr, "urn:s:%lu", i % (nt / 100));
        sprintf(pstr, "urn:p:%lu", i % (nt / 1000));
        sprintf(ostr, "urn:o:%lu", i);
        LSUP_triple_init(
                trp + i, LSUP_iriref_new (sstr, NULL),
                LSUP_iriref_new (pstr, NULL), LSUP_iriref_new (ostr, NULL));
    }
    LSUP_triple_init (trp + nt, NULL, NULL, NULL);
    log_info ("Triples generated.");

    return trp;
}


int main(int argc, char *argv[])
{
    size_t nt = (argc > 1) ? atoi (argv[1]) : NT;
    // Set env variable to test path.
    putenv ("LSUP_MDB_STORE_PATH=" TMPDIR "/lsup_profile_mdb");
    // Clear out database from previous test.
    rm_r (getenv ("LSUP_MDB_STORE_PATH"));

    if (LSUP_init() != LSUP_OK) {
        log_fatal ("Failed to initialize LSUP environment.");
        exit (-1);
    }

    int rc;
    clock_t start, tc1, tc2, end;
    double wallclock, rate;

    log_info ("Generating %lu triples.", nt);
    start = clock();

    LSUP_Triple *trp = generate_triples(nt);
    tc1 = clock();
    wallclock = (double) (tc1 - start) / CLOCKS_PER_SEC;
    log_info ("Time elapsed: %lf s", wallclock);

    log_info ("Inserting triples.");
    LSUP_Graph *gr = LSUP_graph_new (
            LSUP_iriref_new (NULL, NULL), LSUP_STORE_MDB);
    if (!gr) {
        log_error ("Error creating graph!");
        return -1;
    }

    size_t ct;
    rc = LSUP_graph_add(gr, trp, &ct);
    if (rc != LSUP_OK) log_warn ("Graph loading interrupted: %d.", rc);
    else log_info ("Graph populated with %lu triples.", ct);

    for (size_t i = 0; i < nt; i++) {
        LSUP_term_free (trp[i].s);
        LSUP_term_free (trp[i].p);
        LSUP_term_free (trp[i].o);
    }
    free (trp);

    tc2 = clock();
    wallclock = (double) (tc2 - tc1) / CLOCKS_PER_SEC;
    log_info ("Time elapsed: %lf s", wallclock);
    log_info ("Graph size: %lu", LSUP_graph_size (gr));

    log_info ("Lookup...");
    ct = 0;
    LSUP_Triple *spo = TRP_DUMMY;
    LSUP_Term *s = LSUP_iriref_new ("urn:s:8", NULL);
    LSUP_Term *p = LSUP_iriref_new ("urn:p:0", NULL);
    LSUP_Term *o = LSUP_iriref_new ("urn:o:300", NULL);
    LSUP_GraphIterator *it = LSUP_graph_lookup(gr, s, NULL, NULL, &ct);
    log_info ("Found triples by count: %lu", ct);
    ct = 0;
    while (LSUP_graph_iter_next (it, spo) != LSUP_END)
        ct ++;
    log_info ("Found triples by iteration: %lu", ct);
    LSUP_graph_iter_free (it);
    end = clock();
    wallclock = (double) (end - tc2) / CLOCKS_PER_SEC;
    log_info ("Time elapsed: %lf s", wallclock);

    wallclock = (double) (end - start) / CLOCKS_PER_SEC;
    rate = nt / wallclock;
    log_info (
            "%d triples created and inserted in %lf s (%lf triples/s)",
            nt, wallclock, rate);

    LSUP_term_free (s);
    LSUP_term_free (p);
    LSUP_term_free (o);
    LSUP_graph_free(gr);

    return rc;
}