/*
 * 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.tinkerpop.gremlin;

import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.Comparators;
import org.apache.tinkerpop.gremlin.util.TestSupport;
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assume.assumeThat;

/**
 * Utility methods for test development.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 *
 * NOTE: This class duplicates the TestHelper class from gremlin-core. One of them must be removed.
 */
public final class TestHelper extends TestSupport {private static final Logger logger = LoggerFactory.getLogger(TestSupport.class);

    public static final Random RANDOM;

    static {
        final long seed = Long.parseLong(System.getProperty("testSeed", String.valueOf(System.currentTimeMillis())));
        logger.info("*** THE RANDOM TEST SEED IS {} ***", seed);
        RANDOM = new Random(seed);
    }

    private TestHelper() {
    }
    
    public static String convertToRelative(final Class clazz, final File f) {
        final File root = getRootOfBuildDirectory(clazz).getParentFile();
        return root.toURI().relativize(f.toURI()).toString();
    }

    /**
     * Used at the start of a test to make it one that should only be executed when the {@code assertNonDeterministic}
     * system property is set to {@code true}. Tests that call this method are ones that may sometimes fail in certain
     * environments or behave in other random ways. Usually such tests should be removed or re-worked, but there are
     * situations where that may not be possible as there is no other good way to test the feature. In these cases, the
     * tests won't fail a standard build. For this benefit, the downside is that the feature isn't tested as often as
     * it would otherwise, since the {@code assertNonDeterministic} option is not used often and definitely not in
     * automated builds like Travis.
     */
    public static void assumeNonDeterministic() {
        assumeThat("Set the 'assertNonDeterministic' property to true to execute this test",
                System.getProperty("assertNonDeterministic"), is("true"));
    }
        
    ///////////////

    public static void validateVertexEquality(final Vertex originalVertex, final Vertex otherVertex, boolean testEdges) {
        assertEquals(originalVertex, otherVertex);
        assertEquals(otherVertex, originalVertex);
        assertEquals(originalVertex.id(), otherVertex.id());
        assertEquals(originalVertex.label(), otherVertex.label());
        assertEquals(originalVertex.keys().size(), otherVertex.keys().size());
        for (final String key : originalVertex.keys()) {
            final List<VertexProperty<Object>> originalVertexProperties = IteratorUtils.list(originalVertex.properties(key));
            final List<VertexProperty<Object>> otherVertexProperties = IteratorUtils.list(otherVertex.properties(key));
            assertEquals(originalVertexProperties.size(), otherVertexProperties.size());
            for (VertexProperty<Object> originalVertexProperty : originalVertexProperties) {
                final VertexProperty<Object> otherVertexProperty = otherVertexProperties.parallelStream().filter(vp -> vp.equals(originalVertexProperty)).findAny().get();
                validateVertexPropertyEquality(originalVertexProperty, otherVertexProperty);
            }
        }
        if (testEdges) {
            Iterator<Edge> originalEdges = IteratorUtils.list(originalVertex.edges(Direction.OUT), Comparators.ELEMENT_COMPARATOR).iterator();
            Iterator<Edge> otherEdges = IteratorUtils.list(otherVertex.edges(Direction.OUT), Comparators.ELEMENT_COMPARATOR).iterator();
            while (originalEdges.hasNext()) {
                validateEdgeEquality(originalEdges.next(), otherEdges.next());
            }
            assertFalse(otherEdges.hasNext());

            originalEdges = IteratorUtils.list(originalVertex.edges(Direction.IN), Comparators.ELEMENT_COMPARATOR).iterator();
            otherEdges = IteratorUtils.list(otherVertex.edges(Direction.IN), Comparators.ELEMENT_COMPARATOR).iterator();
            while (originalEdges.hasNext()) {
                validateEdgeEquality(originalEdges.next(), otherEdges.next());
            }
            assertFalse(otherEdges.hasNext());
        }

    }

    public static void validateVertexPropertyEquality(final VertexProperty originalVertexProperty, final VertexProperty otherVertexProperty) {
        assertEquals(originalVertexProperty, otherVertexProperty);
        assertEquals(otherVertexProperty, originalVertexProperty);

        if (originalVertexProperty.isPresent()) {
            assertEquals(originalVertexProperty.key(), otherVertexProperty.key());
            assertEquals(originalVertexProperty.value(), otherVertexProperty.value());
            assertEquals(originalVertexProperty.element(), otherVertexProperty.element());

            final boolean originalSupportsMetaProperties = originalVertexProperty.graph().features().vertex().supportsMetaProperties();
            final boolean otherSupportsMetaProperties = otherVertexProperty.graph().features().vertex().supportsMetaProperties();

            // if one supports and the other doesn't then neither should have meta properties.
            if (originalSupportsMetaProperties && !otherSupportsMetaProperties)
                assertEquals(0, originalVertexProperty.keys().size());
            else if (!originalSupportsMetaProperties && otherSupportsMetaProperties)
                assertEquals(0, otherVertexProperty.keys().size());
            else {
                // both support it, so assert in full
                assertEquals(originalVertexProperty.keys().size(), otherVertexProperty.keys().size());
                for (final String key : originalVertexProperty.keys()) {
                    validatePropertyEquality(originalVertexProperty.property(key), otherVertexProperty.property(key));
                }
            }
        }
    }

    public static void validatePropertyEquality(final Property originalProperty, final Property otherProperty) {
        assertEquals(originalProperty, otherProperty);
        assertEquals(otherProperty, originalProperty);
        if (originalProperty.isPresent()) {
            assertEquals(originalProperty.key(), otherProperty.key());
            assertEquals(originalProperty.value(), otherProperty.value());
            assertEquals(originalProperty.element(), otherProperty.element());
        }
    }

    public static void validateEdgeEquality(final Edge originalEdge, final Edge otherEdge) {
        assertEquals(originalEdge, otherEdge);
        assertEquals(otherEdge, originalEdge);
        assertEquals(originalEdge.id(), otherEdge.id());
        assertEquals(originalEdge.label(), otherEdge.label());
        assertEquals(originalEdge.inVertex(), otherEdge.inVertex());
        assertEquals(originalEdge.outVertex(), otherEdge.outVertex());
        assertEquals(originalEdge.keys().size(), otherEdge.keys().size());
        for (final String key : originalEdge.keys()) {
            validatePropertyEquality(originalEdge.property(key), otherEdge.property(key));
        }
    }

    public static void validateEquality(final Object original, final Object other) {
        if (original instanceof Vertex)
            validateVertexEquality((Vertex) original, (Vertex) other, true);
        else if (original instanceof VertexProperty)
            validateVertexPropertyEquality((VertexProperty) original, (VertexProperty) other);
        else if (original instanceof Edge)
            validateEdgeEquality((Edge) original, (Edge) other);
        else if (original instanceof Property)
            validatePropertyEquality((Property) original, (Property) other);
        else
            throw new IllegalArgumentException("The provided object must be a graph object: " + original.getClass().getCanonicalName());
    }

    public static void createRandomGraph(final Graph graph, final int numberOfVertices, final int maxNumberOfEdgesPerVertex) {
        final Random random = new Random();
        for (int i = 0; i < numberOfVertices; i++) {
            graph.addVertex(T.id, i);
        }
        graph.vertices().forEachRemaining(vertex -> {
            for (int i = 0; i < random.nextInt(maxNumberOfEdgesPerVertex); i++) {
                final Vertex other = graph.vertices(random.nextInt(numberOfVertices)).next();
                vertex.addEdge("link", other);
            }
        });
    }
}
