/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.rdf.api;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;

import org.junit.Assume;
import org.junit.Before;
import org.junit.Test;

/**
 * Test Graph implementation
 * <p>
 * To add to your implementation's tests, create a subclass with a name ending
 * in <code>Test</code> and provide {@link #createFactory()} which minimally
 * must support {@link RDF#createGraph()} and {@link RDF#createIRI(String)}, but
 * ideally support all operations.
 * <p>
 * This test uses try-with-resources blocks for calls to {@link Graph#stream()}
 * and {@link Graph#iterate()}.
 *
 * @see Graph
 * @see RDF
 */
public abstract class AbstractGraphTest {

    protected RDF factory;
    protected Graph graph;
    protected IRI alice;
    protected IRI bob;
    protected IRI name;
    protected IRI knows;
    protected IRI member;
    protected BlankNode bnode1;
    protected BlankNode bnode2;
    protected Literal aliceName;
    protected Literal bobName;
    protected Literal secretClubName;
    protected Literal companyName;
    protected Triple bobNameTriple;

    /**
     *
     * This method must be overridden by the implementing test to provide a
     * factory for the test to create {@link Graph}, {@link IRI} etc.
     *
     * @return {@link RDF} instance to be tested.
     */
    protected abstract RDF createFactory();

    @Before
    public void createGraphAndAdd() {
        factory = createFactory();
        graph = factory.createGraph();
        assertEquals(0, graph.size());

        alice = factory.createIRI("http://example.com/alice");
        bob = factory.createIRI("http://example.com/bob");
        name = factory.createIRI("http://xmlns.com/foaf/0.1/name");
        knows = factory.createIRI("http://xmlns.com/foaf/0.1/knows");
        member = factory.createIRI("http://xmlns.com/foaf/0.1/member");
        try {
            bnode1 = factory.createBlankNode("org1");
            bnode2 = factory.createBlankNode("org2");
        } catch (final UnsupportedOperationException ex) {
            // leave as null
        }

        try {
            secretClubName = factory.createLiteral("The Secret Club");
            companyName = factory.createLiteral("A company");
            aliceName = factory.createLiteral("Alice");
            bobName = factory.createLiteral("Bob", "en-US");
        } catch (final UnsupportedOperationException ex) {
            // leave as null
        }

        if (aliceName != null) {
            graph.add(alice, name, aliceName);
        }
        graph.add(alice, knows, bob);

        if (bnode1 != null) {
            graph.add(alice, member, bnode1);
        }

        if (bobName != null) {
            try {
                bobNameTriple = factory.createTriple(bob, name, bobName);
            } catch (final UnsupportedOperationException ex) {
                // leave as null
            }
            if (bobNameTriple != null) {
                graph.add(bobNameTriple);
            }
        }
        if (bnode1 != null) {
            graph.add(factory.createTriple(bob, member, bnode1));
            graph.add(factory.createTriple(bob, member, bnode2));
            if (secretClubName != null) {
                graph.add(bnode1, name, secretClubName);
                graph.add(bnode2, name, companyName);
            }
        }
    }

    @Test
    public void size() throws Exception {
        assertFalse(graph.isEmpty());
        Assume.assumeNotNull(bnode1, bnode2, aliceName, bobName, secretClubName, companyName, bobNameTriple);
        // Can only reliably predict size if we could create all triples
        assertEquals(8, graph.size());
    }

    @Test
    public void iterate() throws Exception {

        Assume.assumeFalse(graph.isEmpty());

        final List<Triple> triples = new ArrayList<>();
        for (final Triple t : graph.iterate()) {
            triples.add(t);
        }
        assertEquals(graph.size(), triples.size());
        if (bobNameTriple != null) {
            assertTrue(triples.contains(bobNameTriple));
        }

        // aborted iteration
        final Iterable<Triple> iterate = graph.iterate();
        final Iterator<Triple> it = iterate.iterator();

        assertTrue(it.hasNext());
        it.next();
        closeIterable(iterate);

        // second iteration - should start from fresh and
        // get the same count
        long count = 0;
        final Iterable<Triple> iterable = graph.iterate();
        for (@SuppressWarnings("unused") final
        Triple t : iterable) {
            count++;
        }
        assertEquals(graph.size(), count);
    }

    /**
     * Special triple closing for RDF4J.
     */
    private void closeIterable(final Iterable<Triple> iterate) throws Exception {
        if (iterate instanceof AutoCloseable) {
            ((AutoCloseable) iterate).close();
        }
    }

    @Test
    public void iterateFilter() throws Exception {
        final List<RDFTerm> friends = new ArrayList<>();
        final IRI alice = factory.createIRI("http://example.com/alice");
        final IRI knows = factory.createIRI("http://xmlns.com/foaf/0.1/knows");
        for (final Triple t : graph.iterate(alice, knows, null)) {
            friends.add(t.getObject());
        }
        assertEquals(1, friends.size());
        assertEquals(bob, friends.get(0));

        // .. can we iterate over zero hits?
        final Iterable<Triple> iterate = graph.iterate(bob, knows, alice);
        for (final Triple unexpected : iterate) {
            fail("Unexpected triple " + unexpected);
        }
        // closeIterable(iterate);
    }

    @Test
    public void contains() throws Exception {
        assertFalse(graph.contains(bob, knows, alice)); // or so he claims..

        assertTrue(graph.contains(alice, knows, bob));

        try (Stream<? extends Triple> stream = graph.stream()) {
            final Optional<? extends Triple> first = stream.skip(4).findFirst();
            Assume.assumeTrue(first.isPresent());
            final Triple existingTriple = first.get();
            assertTrue(graph.contains(existingTriple));
        }

        final Triple nonExistingTriple = factory.createTriple(bob, knows, alice);
        assertFalse(graph.contains(nonExistingTriple));

        Triple triple = null;
        try {
            triple = factory.createTriple(alice, knows, bob);
        } catch (final UnsupportedOperationException ex) {
        }
        if (triple != null) {
            // FIXME: Should not this always be true?
            // assertTrue(graph.contains(triple));
        }
    }

    @Test
    public void remove() throws Exception {
        final long fullSize = graph.size();
        graph.remove(alice, knows, bob);
        final long shrunkSize = graph.size();
        assertEquals(1, fullSize - shrunkSize);

        graph.remove(alice, knows, bob);
        assertEquals(shrunkSize, graph.size()); // unchanged

        graph.add(alice, knows, bob);
        graph.add(alice, knows, bob);
        graph.add(alice, knows, bob);
        // Undetermined size at this point -- but at least it
        // should be bigger
        assertTrue(graph.size() > shrunkSize);

        // and after a single remove they should all be gone
        graph.remove(alice, knows, bob);
        assertEquals(shrunkSize, graph.size());

        Triple otherTriple;
        try (Stream<? extends Triple> stream = graph.stream()) {
            final Optional<? extends Triple> anyTriple = stream.findAny();
            Assume.assumeTrue(anyTriple.isPresent());
            otherTriple = anyTriple.get();
        }

        graph.remove(otherTriple);
        assertEquals(shrunkSize - 1, graph.size());
        graph.remove(otherTriple);
        assertEquals(shrunkSize - 1, graph.size()); // no change

        // for some reason in rdf4j this causes duplicates!
        graph.add(otherTriple);
        // graph.stream().forEach(System.out::println);
        // should have increased
        assertTrue(graph.size() >= shrunkSize);
    }

    @Test
    public void clear() throws Exception {
        graph.clear();
        assertFalse(graph.contains(alice, knows, bob));
        assertEquals(0, graph.size());
        graph.clear(); // no-op
        assertEquals(0, graph.size());
    }

    @Test
    public void getTriples() throws Exception {
        long tripleCount;
        try (Stream<? extends Triple> stream = graph.stream()) {
            tripleCount = stream.count();
        }
        assertTrue(tripleCount > 0);

        try (Stream<? extends Triple> stream = graph.stream()) {
            assertTrue(stream.allMatch(t -> graph.contains(t)));
        }

        // Check exact count
        Assume.assumeNotNull(bnode1, bnode2, aliceName, bobName, secretClubName, companyName, bobNameTriple);
        assertEquals(8, tripleCount);
    }

    @Test
    public void getTriplesQuery() throws Exception {

        try (Stream<? extends Triple> stream = graph.stream(alice, null, null)) {
            final long aliceCount = stream.count();
            assertTrue(aliceCount > 0);
            Assume.assumeNotNull(aliceName);
            assertEquals(3, aliceCount);
        }

        Assume.assumeNotNull(bnode1, bnode2, bobName, companyName, secretClubName);
        try (Stream<? extends Triple> stream = graph.stream(null, name, null)) {
            assertEquals(4, stream.count());
        }
        Assume.assumeNotNull(bnode1);
        try (Stream<? extends Triple> stream = graph.stream(null, member, null)) {
            assertEquals(3, stream.count());
        }
    }

    @Test
    public void addBlankNodesFromMultipleGraphs() throws Exception {

        // Create two separate Graph instances
        // and add them to a new Graph g3
        try (final Graph g1 = createGraph1(); final Graph g2 = createGraph2(); final Graph g3 = factory.createGraph()) {
            addAllTriples(g1, g3);
            addAllTriples(g2, g3);

            // Let's make a map to find all those blank nodes after insertion
            // (The Graph implementation is not currently required to
            // keep supporting those BlankNodes with contains() - see
            // COMMONSRDF-15)

            final Map<String, BlankNodeOrIRI> whoIsWho = new ConcurrentHashMap<>();
            // ConcurrentHashMap as we will try parallel forEach below,
            // which should not give inconsistent results (it does with a
            // HashMap!)

            // look up BlankNodes by name
            final IRI name = factory.createIRI("http://xmlns.com/foaf/0.1/name");
            try (Stream<? extends Triple> stream = g3.stream(null, name, null)) {
                stream.parallel().forEach(t -> whoIsWho.put(t.getObject().ntriplesString(), t.getSubject()));
            }

            assertEquals(4, whoIsWho.size());
            // and contains 4 unique values
            assertEquals(4, new HashSet<>(whoIsWho.values()).size());

            final BlankNodeOrIRI b1Alice = whoIsWho.get("\"Alice\"");
            assertNotNull(b1Alice);
            final BlankNodeOrIRI b2Bob = whoIsWho.get("\"Bob\"");
            assertNotNull(b2Bob);
            final BlankNodeOrIRI b1Charlie = whoIsWho.get("\"Charlie\"");
            assertNotNull(b1Charlie);
            final BlankNodeOrIRI b2Dave = whoIsWho.get("\"Dave\"");
            assertNotNull(b2Dave);

            // All blank nodes should differ
            notEquals(b1Alice, b2Bob);
            notEquals(b1Alice, b1Charlie);
            notEquals(b1Alice, b2Dave);
            notEquals(b2Bob, b1Charlie);
            notEquals(b2Bob, b2Dave);
            notEquals(b1Charlie, b2Dave);

            // And we should be able to query with them again
            // as we got them back from g3
            final IRI hasChild = factory.createIRI("http://example.com/hasChild");
            assertTrue(g3.contains(b1Alice, hasChild, b2Bob));
            assertTrue(g3.contains(b2Dave, hasChild, b1Charlie));
            // But not
            assertFalse(g3.contains(b1Alice, hasChild, b1Alice));
            assertFalse(g3.contains(b1Alice, hasChild, b1Charlie));
            assertFalse(g3.contains(b1Alice, hasChild, b2Dave));
            // nor
            assertFalse(g3.contains(b2Dave, hasChild, b1Alice));
            assertFalse(g3.contains(b2Dave, hasChild, b1Alice));

            // and these don't have any children (as far as we know)
            assertFalse(g3.contains(b2Bob, hasChild, null));
            assertFalse(g3.contains(b1Charlie, hasChild, null));
        } catch (final UnsupportedOperationException ex) {
            Assume.assumeNoException(ex);
        }
    }

    @Test
    public void containsLanguageTagsCaseInsensitive() throws Exception {
        // COMMONSRDF-51: Ensure we can add/contains/remove with any casing
        // of literal language tag
        final Literal lower = factory.createLiteral("Hello", "en-gb");
        final Literal upper = factory.createLiteral("Hello", "EN-GB");
        final Literal mixed = factory.createLiteral("Hello", "en-GB");

        final IRI example1 = factory.createIRI("http://example.com/s1");
        final IRI greeting = factory.createIRI("http://example.com/greeting");

        try (final Graph graph = factory.createGraph()) {
            graph.add(example1, greeting, upper);

            // any kind of Triple should match
            assertTrue(graph.contains(factory.createTriple(example1, greeting, upper)));
            assertTrue(graph.contains(factory.createTriple(example1, greeting, lower)));
            assertTrue(graph.contains(factory.createTriple(example1, greeting, mixed)));

            // or as patterns
            assertTrue(graph.contains(null, null, upper));
            assertTrue(graph.contains(null, null, lower));
            assertTrue(graph.contains(null, null, mixed));
        }
    }

    @Test
    public void containsLanguageTagsCaseInsensitiveTurkish() throws Exception {
        // COMMONSRDF-51: Special test for Turkish issue where
        // "i".toLowerCase() != "i"
        // See also:
        // https://garygregory.wordpress.com/2015/11/03/java-lowercase-conversion-turkey/

        // This is similar to the test in AbstractRDFTest, but on a graph
        final Locale defaultLocale = Locale.getDefault();
        try (final Graph g = factory.createGraph()) {
            Locale.setDefault(Locale.ROOT);
            final Literal lowerROOT = factory.createLiteral("moi", "fi");
            final Literal upperROOT = factory.createLiteral("moi", "FI");
            final Literal mixedROOT = factory.createLiteral("moi", "fI");
            final IRI exampleROOT = factory.createIRI("http://example.com/s1");
            final IRI greeting = factory.createIRI("http://example.com/greeting");
            g.add(exampleROOT, greeting, mixedROOT);

            final Locale turkish = Locale.forLanguageTag("TR");
            Locale.setDefault(turkish);
            // If the below assertion fails, then the Turkish
            // locale no longer have this peculiarity that
            // we want to test.
            Assume.assumeFalse("FI".toLowerCase().equals("fi"));

            // Below is pretty much the same as in
            // containsLanguageTagsCaseInsensitive()
            final Literal lower = factory.createLiteral("moi", "fi");
            final Literal upper = factory.createLiteral("moi", "FI");
            final Literal mixed = factory.createLiteral("moi", "fI");

            final IRI exampleTR = factory.createIRI("http://example.com/s2");
            g.add(exampleTR, greeting, upper);
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, upper)));
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, upperROOT)));
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, lower)));
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, lowerROOT)));
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, mixed)));
            assertTrue(g.contains(factory.createTriple(exampleTR, greeting, mixedROOT)));
            assertTrue(g.contains(exampleTR, null, upper));
            assertTrue(g.contains(exampleTR, null, upperROOT));
            assertTrue(g.contains(exampleTR, null, lower));
            assertTrue(g.contains(exampleTR, null, lowerROOT));
            assertTrue(g.contains(exampleTR, null, mixed));
            assertTrue(g.contains(exampleTR, null, mixedROOT));

            // What about the triple we added while in ROOT locale?
            assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, upper)));
            assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, lower)));
            assertTrue(g.contains(factory.createTriple(exampleROOT, greeting, mixed)));
            assertTrue(g.contains(exampleROOT, null, upper));
            assertTrue(g.contains(exampleROOT, null, lower));
            assertTrue(g.contains(exampleROOT, null, mixed));
        } finally {
            Locale.setDefault(defaultLocale);
        }
    }


    @Test
    public void removeLanguageTagsCaseInsensitive() throws Exception {
        // COMMONSRDF-51: Ensure we can remove with any casing
        // of literal language tag
        final Literal lower = factory.createLiteral("Hello", "en-gb");
        final Literal upper = factory.createLiteral("Hello", "EN-GB");
        final Literal mixed = factory.createLiteral("Hello", "en-GB");

        final IRI example1 = factory.createIRI("http://example.com/s1");
        final IRI greeting = factory.createIRI("http://example.com/greeting");

        try (final Graph graph = factory.createGraph()) {
            graph.add(example1, greeting, upper);

            // Remove should also honor any case
            graph.remove(example1, null, mixed);
            assertFalse(graph.contains(null, greeting, null));

            graph.add(example1, greeting, lower);
            graph.remove(example1, null, upper);

            // Check with Triple
            graph.add(factory.createTriple(example1, greeting, mixed));
            graph.remove(factory.createTriple(example1, greeting, upper));
            assertFalse(graph.contains(null, greeting, null));
        }
    }

    private static Optional<? extends Triple> closableFindAny(final Stream<? extends Triple> stream) {
        try (Stream<? extends Triple> s = stream) {
            return s.findAny();
        }
    }

    @Test
    public void streamLanguageTagsCaseInsensitive() throws Exception {
        // COMMONSRDF-51: Ensure we can add/contains/remove with any casing
        // of literal language tag
        final Literal lower = factory.createLiteral("Hello", "en-gb");
        final Literal upper = factory.createLiteral("Hello", "EN-GB");
        final Literal mixed = factory.createLiteral("Hello", "en-GB");

        final IRI example1 = factory.createIRI("http://example.com/s1");
        final IRI greeting = factory.createIRI("http://example.com/greeting");

        try (final Graph graph = factory.createGraph()) {
            graph.add(example1, greeting, upper);

            // or as patterns
            assertTrue(closableFindAny(graph.stream(null, null, upper)).isPresent());
            assertTrue(closableFindAny(graph.stream(null, null, lower)).isPresent());
            assertTrue(closableFindAny(graph.stream(null, null, mixed)).isPresent());

            // Check the triples returned equal a new triple
            final Triple t = closableFindAny(graph.stream(null, null, lower)).get();
            assertEquals(t, factory.createTriple(example1, greeting, mixed));
        }
    }

    private void notEquals(final BlankNodeOrIRI node1, final BlankNodeOrIRI node2) {
        assertFalse(node1.equals(node2));
        // in which case we should be able to assume
        // (as they are in the same graph)
        assertFalse(node1.ntriplesString().equals(node2.ntriplesString()));
    }

    /**
     * Add all triples from the source to the target.
     * <p>
     * The triples may be copied in any order. No special conversion or
     * adaptation of {@link BlankNode}s are performed.
     *
     * @param source
     *            Source Graph to copy triples from
     * @param target
     *            Target Graph where triples will be added
     */
    private void addAllTriples(final Graph source, final Graph target) {

        // unordered() as we don't need to preserve triple order
        // sequential() as we don't (currently) require target Graph to be
        // thread-safe

        try (Stream<? extends Triple> stream = source.stream()) {
            stream.unordered().sequential().forEach(t -> target.add(t));
        }
    }

    /**
     * Make a new graph with two BlankNodes - each with a different
     * uniqueReference
     */
    private Graph createGraph1() {
        final RDF factory1 = createFactory();

        final IRI name = factory1.createIRI("http://xmlns.com/foaf/0.1/name");
        final Graph g1 = factory1.createGraph();
        final BlankNode b1 = createOwnBlankNode("b1", "0240eaaa-d33e-4fc0-a4f1-169d6ced3680");
        g1.add(b1, name, factory1.createLiteral("Alice"));

        final BlankNode b2 = createOwnBlankNode("b2", "9de7db45-0ce7-4b0f-a1ce-c9680ffcfd9f");
        g1.add(b2, name, factory1.createLiteral("Bob"));

        final IRI hasChild = factory1.createIRI("http://example.com/hasChild");
        g1.add(b1, hasChild, b2);

        return g1;
    }

    /**
     * Create a different implementation of BlankNode to be tested with
     * graph.add(a,b,c); (the implementation may or may not then choose to
     * translate such to its own instances)
     *
     * @param name
     * @return
     */
    private BlankNode createOwnBlankNode(final String name, final String uuid) {
        return new BlankNode() {
            @Override
            public String ntriplesString() {
                return "_: " + name;
            }

            @Override
            public String uniqueReference() {
                return uuid;
            }

            @Override
            public int hashCode() {
                return uuid.hashCode();
            }

            @Override
            public boolean equals(final Object obj) {
                if (!(obj instanceof BlankNode)) {
                    return false;
                }
                final BlankNode other = (BlankNode) obj;
                return uuid.equals(other.uniqueReference());
            }
        };
    }

    private Graph createGraph2() {
        final RDF factory2 = createFactory();
        final IRI name = factory2.createIRI("http://xmlns.com/foaf/0.1/name");

        final Graph g2 = factory2.createGraph();

        final BlankNode b1 = createOwnBlankNode("b1", "bc8d3e45-a08f-421d-85b3-c25b373abf87");
        g2.add(b1, name, factory2.createLiteral("Charlie"));

        final BlankNode b2 = createOwnBlankNode("b2", "2209097a-5078-4b03-801a-6a2d2f50d739");
        g2.add(b2, name, factory2.createLiteral("Dave"));

        final IRI hasChild = factory2.createIRI("http://example.com/hasChild");
        // NOTE: Opposite direction of loadGraph1
        g2.add(b2, hasChild, b1);
        return g2;
    }

    /**
     * An attempt to use the Java 8 streams to look up a more complicated query.
     * <p>
     * FYI, the equivalent SPARQL version (untested):
     *
     * <pre>
     *     SELECT ?orgName WHERE {
     *             ?org foaf:name ?orgName .
     *             ?alice foaf:member ?org .
     *             ?bob foaf:member ?org .
     *             ?alice foaf:knows ?bob .
     *           FILTER NOT EXIST { ?bob foaf:knows ?alice }
     *    }
     * </pre>
     *
     * @throws Exception If test fails
     */
    @Test
    public void whyJavaStreamsMightNotTakeOverFromSparql() throws Exception {
        Assume.assumeNotNull(bnode1, bnode2, secretClubName);
        // Find a secret organizations
        try (Stream<? extends Triple> stream = graph.stream(null, knows, null)) {
            assertEquals("\"The Secret Club\"",
                    // Find One-way "knows"
                    stream.filter(t -> !graph.contains((BlankNodeOrIRI) t.getObject(), knows, t.getSubject()))
                            .map(knowsTriple -> {
                                try (Stream<? extends Triple> memberOf = graph
                                        // and those they know, what are they
                                        // member of?
                                        .stream((BlankNodeOrIRI) knowsTriple.getObject(), member, null)) {
                                    return memberOf
                                            // keep those which first-guy is a
                                            // member of
                                            .filter(memberTriple -> graph.contains(knowsTriple.getSubject(), member,
                                                    // First hit is good enough
                                                    memberTriple.getObject()))
                                            .findFirst().get().getObject();
                                }
                            })
                            // then look up the name of that org
                            .map(org -> {
                                try (Stream<? extends Triple> orgName = graph.stream((BlankNodeOrIRI) org, name,
                                        null)) {
                                    return orgName.findFirst().get().getObject().ntriplesString();
                                }
                            }).findFirst().get());
        }
    }
}
