/*
 * 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.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_P_S_SE_SL_Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_LP_O_S_SE_SL_Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_S_SE_SL_Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.B_O_Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.traverser.O_Traverser;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

/**
 * Those developing Gremlin implementations must provide a GraphProvider implementation so that the
 * different test suites know how to instantiate their implementations.  Implementers may choose to have multiple
 * {@code GraphProvider} implementations to mix and match with multiple test suite implementations.  For example,
 * create one {@code GraphProvider} that has no indices defined and a separate {@code GraphProvider} that has
 * indices.  Then create separate test suite implementations for each {@code GraphProvider}.  This approach will
 * have the test suites executed once for each {@code GraphProvider} ensuring that the {@link Graph} implementation
 * works under multiple configurations.  Consider making these "extra" tests "integration tests" so that they
 * don't have to be executed on every run of the build so as to save time.  Run the "integration tests" periodically
 * to ensure overall compliance.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public interface GraphProvider {

    /**
     * Implementations from {@code gremlin-core} that need to be part of the clear process.  This does not exempt
     * providers from having to register their extensions to any of these classes, but does prevent them from
     * having to register them in addition to their own.
     */
    public static final Set<Class> CORE_IMPLEMENTATIONS = new HashSet<Class>() {{
        add(__.class);
        add(DefaultGraphTraversal.class);
        add(GraphTraversalSource.class);
        add(B_O_S_SE_SL_Traverser.class);
        add(B_LP_O_P_S_SE_SL_Traverser.class);
        add(B_LP_O_S_SE_SL_Traverser.class);
        add(B_O_Traverser.class);
        add(O_Traverser.class);
    }};

    /**
     * Create a {@link GraphTraversalSource} from a {@link Graph} instance.  The default implementation does not
     * use {@link GraphComputer} so providers should override as necessary if their implementation is testing
     * something that requires a different engine type, like {@link GraphComputer}.
     */
    public default GraphTraversalSource traversal(final Graph graph) {
        return graph.traversal();
    }

    /**
     * Create a {@link GraphTraversalSource} from a {@link Graph} instance.  The default implementation does not use
     * {@link GraphComputer} so providers should override as necessary if their implementation is testing
     * something that requires a different engine type, like {@link GraphComputer}.
     * <p/>
     * Implementations should apply strategies as necessary to the
     * {@link GraphTraversalSource} before calling it's {@code create} method.
     */
    public default GraphTraversalSource traversal(final Graph graph, final TraversalStrategy... strategies) {
        return this.traversal(graph).withStrategies(strategies);
    }

    /**
     * Create a {@link GraphComputer} from the {@link Graph} instance. The default implementation simply calls {@code graph.compute()}.
     *
     * @param graph the graph to get the graph computer from
     * @return a new graph computer
     */
    public default GraphComputer getGraphComputer(final Graph graph) {
        return graph.compute();
    }

    /**
     * Creates a new {@link Graph} instance using the default
     * {@code org.apache.commons.configuration.Configuration} from
     * {@link #standardGraphConfiguration(Class, String, LoadGraphWith.GraphData)}.
     */
    default public Graph standardTestGraph(final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData loadGraphWith) {
        return GraphFactory.open(standardGraphConfiguration(test, testMethodName, loadGraphWith));
    }

    /**
     * Creates a new {@link Graph} instance from the {@code Configuration} object using {@link GraphFactory}.
     * The assumption here is that the {@code Configuration} has been created by one of the
     * {@link #newGraphConfiguration(String, Class, String, LoadGraphWith.GraphData)} methods and has therefore
     * already been modified by the implementation as necessary for {@link Graph} creation.
     */
    default public Graph openTestGraph(final Configuration config) {
        return GraphFactory.open(config);
    }

    /**
     * Gets the {@code Configuration} object that can construct a {@link Graph} instance from {@link GraphFactory}.
     * Note that this method should create a {@link Graph} using the {@code graphName} of "standard", meaning it
     * should always return a configuration instance that generates the same {@link Graph} from the
     * {@link GraphFactory}.
     */
    default public Configuration standardGraphConfiguration(final Class<?> test, final String testMethodName, final LoadGraphWith.GraphData loadGraphWith) {
        return newGraphConfiguration("standard", test, testMethodName, Collections.<String, Object>emptyMap(), loadGraphWith);
    }

    /**
     * If possible (usually with persisted graph) clear the space on disk given the configuration that would be used
     * to construct the graph.  The default implementation simply calls
     * {@link #clear(Graph, org.apache.commons.configuration.Configuration)} with
     * a null graph argument.
     * <p/>
     * Implementations should be able to accept an argument of null for the {@code org.apache.commons.configuration.Configuration}
     * as well, and a proper handling is needed. Otherwise, a NullPointerException may be thrown.
     */
    public default void clear(final Configuration configuration) throws Exception {
        clear(null, configuration);
    }

    /**
     * Clears a {@link Graph} of all data and settings.  Implementations will have different ways of handling this.
     * It is typically expected that {@link Graph#close()} will be called and open transactions will be closed.
     * For a brute force approach, implementers can simply delete data directories provided in the configuration.
     * Implementers may choose a more elegant approach if it exists.
     * <p/>
     * Implementations should be able to accept an argument of null for the {@code Graph}, in which case the only action
     * that can be performed is a clear given the configuration.  The method will typically be called this way
     * as clean up task on setup to ensure that a persisted graph has a clear space to create a test graph.
     * <p/>
     * Implementations should be able to accept an argument of null for the {@code org.apache.commons.configuration.Configuration}
     * as well, and a proper handling is needed. Otherwise, a NullPointerException may be thrown.
     * <p/>
     * Calls to this method may occur multiple times for a specific test. Develop this method to be idempotent.
     */
    public void clear(final Graph graph, final Configuration configuration) throws Exception;

    /**
     * Converts an identifier from a test to an identifier accepted by the {@link Graph} instance.  Test that try to
     * utilize an Element identifier will pass it to this method before usage.  This method should be sure to
     * be consistent in the return value such that calling it with "x" should always return the same transformed
     * value.
     */
    default public Object convertId(final Object id, final Class<? extends Element> c) {
        return id;
    }

    /**
     * Converts an label from a test to an label accepted by the Graph instance.  Test that try to
     * utilize a label will pass it to this method before usage.
     */
    default public String convertLabel(final String label) {
        return label;
    }

    /**
     * When implementing this method ensure that a test suite can override any settings EXCEPT the
     * "gremlin.graph" setting which should be defined by the implementer. It should provide a
     * {@code Configuration} that will generate a graph unique to that {@code graphName}.
     *
     * @param graphName              a unique test graph name
     * @param test                   the test class
     * @param testMethodName         the name of the test
     * @param configurationOverrides settings to override defaults with.
     * @param loadGraphWith          the data set to load and will be null if no data is to be loaded
     */
    public Configuration newGraphConfiguration(final String graphName,
                                               final Class<?> test,
                                               final String testMethodName,
                                               final Map<String, Object> configurationOverrides,
                                               final LoadGraphWith.GraphData loadGraphWith);

    /**
     * When implementing this method ensure that a test suite can override any settings EXCEPT the
     * "gremlin.graph" setting which should be defined by the implementer. It should provide a
     * {@code Configuration} that will generate a graph unique to that {@code graphName}.
     *
     * @param graphName      a unique test graph name
     * @param test           the test class
     * @param testMethodName the name of the test
     * @param loadGraphWith  the data set to load and will be null if no data is to be loaded
     */
    default public Configuration newGraphConfiguration(final String graphName,
                                                       final Class<?> test,
                                                       final String testMethodName,
                                                       final LoadGraphWith.GraphData loadGraphWith) {
        return newGraphConfiguration(graphName, test, testMethodName, new HashMap<>(), loadGraphWith);
    }

    /**
     * Tests are annotated with a {@link LoadGraphWith} annotation. These annotations tell the test what kind of data
     * to preload into the graph instance.  It is up to the implementation to load the graph with the data specified
     * by that annotation. This method also represents the place where indices should be configured according the
     * the {@link Graph} implementation's API. Implementers can use the {@code testClass} and {@code testName}
     * arguments to implement test specific configurations to their graphs.
     *
     * @param graph         the {@link Graph} instance to load data into constructed by this {@code GraphProvider}
     * @param loadGraphWith the annotation for the currently running test - this value may be null if no graph
     *                      data is to be loaded in front of the test.
     * @param testClass     the test class being executed
     * @param testName      the name of the test method being executed
     */
    public void loadGraphData(final Graph graph, final LoadGraphWith loadGraphWith, final Class testClass, final String testName);

    /**
     * Get the set of concrete implementations of certain classes and interfaces utilized by the test suite. This
     * method should return any implementations or extensions of the following interfaces or classes:
     * <ul>
     * <li>{@link Edge}</li>
     * <li>{@link Element}</li>
     * <li>{@link DefaultGraphTraversal}</li>
     * <li>{@link Graph}</li>
     * <li>{@link Graph.Variables}</li>
     * <li>{@link GraphTraversal}</li>
     * <li>{@link B_LP_O_P_S_SE_SL_Traverser}</li>
     * <li>{@link Property}</li>
     * <li>{@link B_O_S_SE_SL_Traverser}</li>
     * <li>{@link Traversal}</li>
     * <li>{@link Traverser}</li>
     * <li>{@link Vertex}</li>
     * <li>{@link VertexProperty}</li>
     * </ul>
     * <p/>
     * The test suite only enforces registration of the following core structure interfaces (i.e. these classes must
     * be registered or the tests will fail to execute):
     * <ul>
     * <li>{@link Edge}</li>
     * <li>{@link Element}</li>
     * <li>{@link Graph}</li>
     * <li>{@link Graph.Variables}</li>
     * <li>{@link Property}</li>
     * <li>{@link Vertex}</li>
     * <li>{@link VertexProperty}</li>
     * </ul>
     * <p/>
     * The remaining interfaces and classes should be registered however as failure to do so, might cause failures
     * in the Groovy environment testing suite.
     * <p/>
     * Internally speaking, tests that make use of this method should bind in {@link #CORE_IMPLEMENTATIONS} to the
     * {@link Set} because these represent {@code gremlin-core} implementations that are likely not registered
     * by the vendor implementations.
     */
    public Set<Class> getImplementations();

    /**
     * Helper method for those build {@link GraphProvider} implementations that need a standard working directory
     * for tests (e.g. graphs that persist data to disk). Typically, there is no need to override the default
     * behavior of this method and if it is overridden, it is usually best to continue to use the {@link TestHelper}
     * to produce the working directory as it will create the path in the appropriate build directories.
     * @return UNIX-formatted absolute directory path
     */
    public default String getWorkingDirectory() {
        return TestHelper.makeTestDataDirectory(this.getClass(), "graph-provider-data");
    }

    /**
     * Returns a {@link TestListener} implementation that provides feedback to the {@link GraphProvider} implementation.
     * By default, this returns an empty listener.
     */
    public default Optional<TestListener> getTestListener() {
        return Optional.empty();
    }

    /**
     * An annotation to be applied to a {@code GraphProvider} implementation that provides additional information
     * about its intentions. The {@code Descriptor} is required by those {@code GraphProvider} implementations
     * that will be assigned to test suites that use
     * {@link org.apache.tinkerpop.gremlin.process.traversal.TraversalEngine.Type#COMPUTER}.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Inherited
    public @interface Descriptor {

        /**
         * The {@link GraphComputer} implementation that the {@code GraphProvider} will use when it constructs
         * a {@link Traversal} with {@link #traversal(Graph)} or {@link #traversal(Graph, TraversalStrategy[])}.
         * This value should be null if a {@link GraphComputer} is not being used.
         */
        public Class<? extends GraphComputer> computer();
    }

    public interface TestListener {
        public default void onTestStart(final Class<?> test, final String testName) {
            // do nothing
        }

        public default void onTestEnd(final Class<?> test, final String testName) {
            // do nothing
        }
    }
}
