/* global describe, it */

import { Store } from "../pkg/oxigraph.js";
import dataModel from "@rdfjs/data-model";
import assert from "assert";

const ex = dataModel.namedNode("http://example.com");
const triple = dataModel.quad(
    dataModel.blankNode("s"),
    dataModel.namedNode("http://example.com/p"),
    dataModel.literal("o"),
);

describe("Store", function () {
    describe("#add()", function () {
        it("an added quad should be in the store", function () {
            const store = new Store();
            store.add(dataModel.quad(ex, ex, triple));
            assert(store.has(dataModel.quad(ex, ex, triple)));
        });
    });

    describe("#delete()", function () {
        it("an removed quad should not be in the store anymore", function () {
            const store = new Store([dataModel.quad(triple, ex, ex)]);
            assert(store.has(dataModel.quad(triple, ex, ex)));
            store.delete(dataModel.quad(triple, ex, ex));
            assert(!store.has(dataModel.quad(triple, ex, ex)));
        });
    });

    describe("#has()", function () {
        it("an added quad should be in the store", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            assert(store.has(dataModel.quad(ex, ex, ex)));
        });
    });

    describe("#size()", function () {
        it("A store with one quad should have 1 for size", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            assert.strictEqual(1, store.size);
        });
    });

    describe("#match_quads()", function () {
        it("blank pattern should return all quads", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            const results = store.match();
            assert.strictEqual(1, results.length);
            assert(dataModel.quad(ex, ex, ex).equals(results[0]));
        });
    });

    describe("#query()", function () {
        it("ASK true", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            assert.strictEqual(true, store.query("ASK { ?s ?s ?s }"));
        });

        it("ASK false", function () {
            const store = new Store();
            assert.strictEqual(false, store.query("ASK { FILTER(false)}"));
        });

        it("CONSTRUCT", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            const results = store.query("CONSTRUCT { ?s ?p ?o } WHERE { ?s ?p ?o }");
            assert.strictEqual(1, results.length);
            assert(dataModel.quad(ex, ex, ex).equals(results[0]));
        });

        it("SELECT", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            const results = store.query("SELECT ?s WHERE { ?s ?p ?o }");
            assert.strictEqual(1, results.length);
            assert(ex.equals(results[0].get("s")));
        });

        it("SELECT with NOW()", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            const results = store.query(
                "SELECT * WHERE { FILTER(2022 <= YEAR(NOW()) && YEAR(NOW()) <= 2100) }",
            );
            assert.strictEqual(1, results.length);
        });

        it("SELECT with RAND()", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            const results = store.query("SELECT (RAND() AS ?y) WHERE {}");
            assert.strictEqual(1, results.length);
        });
    });

    describe("#update()", function () {
        it("INSERT DATA", function () {
            const store = new Store();
            store.update(
                "INSERT DATA { <http://example.com> <http://example.com> <http://example.com> }",
            );
            assert.strictEqual(1, store.size);
        });

        it("DELETE DATA", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            store.update(
                "DELETE DATA { <http://example.com> <http://example.com> <http://example.com> }",
            );
            assert.strictEqual(0, store.size);
        });

        it("DELETE WHERE", function () {
            const store = new Store([dataModel.quad(ex, ex, ex)]);
            store.update("DELETE WHERE { ?v ?v ?v }");
            assert.strictEqual(0, store.size);
        });
    });

    describe("#load()", function () {
        it("load NTriples in the default graph", function () {
            const store = new Store();
            store.load(
                "<http://example.com> <http://example.com> <http://example.com> .",
                "application/n-triples",
            );
            assert(store.has(dataModel.quad(ex, ex, ex)));
        });

        it("load NTriples in an other graph", function () {
            const store = new Store();
            store.load(
                "<http://example.com> <http://example.com> <http://example.com> .",
                "application/n-triples",
                null,
                ex,
            );
            assert(store.has(dataModel.quad(ex, ex, ex, ex)));
        });

        it("load Turtle with a base IRI", function () {
            const store = new Store();
            store.load(
                "<http://example.com> <http://example.com> <> .",
                "text/turtle",
                "http://example.com",
            );
            assert(store.has(dataModel.quad(ex, ex, ex)));
        });

        it("load NQuads", function () {
            const store = new Store();
            store.load(
                "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .",
                "application/n-quads",
            );
            assert(store.has(dataModel.quad(ex, ex, ex, ex)));
        });

        it("load TriG with a base IRI", function () {
            const store = new Store();
            store.load(
                "GRAPH <> { <http://example.com> <http://example.com> <> }",
                "application/trig",
                "http://example.com",
            );
            assert(store.has(dataModel.quad(ex, ex, ex, ex)));
        });
    });

    describe("#dump()", function () {
        it("dump dataset content", function () {
            const store = new Store([dataModel.quad(ex, ex, ex, ex)]);
            assert.strictEqual(
                "<http://example.com> <http://example.com> <http://example.com> <http://example.com> .\n",
                store.dump("application/n-quads"),
            );
        });

        it("dump named graph content", function () {
            const store = new Store([dataModel.quad(ex, ex, ex, ex)]);
            assert.strictEqual(
                "<http://example.com> <http://example.com> <http://example.com> .\n",
                store.dump("application/n-triples", ex),
            );
        });

        it("dump default graph content", function () {
            const store = new Store([dataModel.quad(ex, ex, ex, ex)]);
            assert.strictEqual("", store.dump("application/n-triples"));
        });
    });
});