/**
 * 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 {
        assertTrue(graph.size() > 0);
        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.assumeTrue(graph.size() > 0);

        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 honour 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());
        }
    }
}
