/*******************************************************************************
 * Copyright (c) 2019 Aston University.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the Eclipse
 * Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
 *
 * Contributors:
 *     Antonio Garcia-Dominguez - initial API and implementation
 ******************************************************************************/
package org.eclipse.hawk.timeaware.tests;

import java.io.File;
import java.util.Collections;
import java.util.Map;

import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.hawk.backend.tests.factories.IGraphDatabaseFactory;
import org.eclipse.hawk.core.IModelIndexer;
import org.eclipse.hawk.core.query.InvalidQueryException;
import org.eclipse.hawk.core.query.QueryExecutionException;
import org.eclipse.hawk.core.security.FileBasedCredentialsStore;
import org.eclipse.hawk.epsilon.emc.EOLQueryEngine;
import org.eclipse.hawk.graph.updater.GraphModelUpdater;
import org.eclipse.hawk.integration.tests.ModelIndexingTest;
import org.eclipse.hawk.integration.tests.mm.Tree.TreeFactory;
import org.eclipse.hawk.svn.SvnManager;
import org.eclipse.hawk.svn.tests.rules.TemporarySVNRepository;
import org.eclipse.hawk.timeaware.graph.TimeAwareIndexer;
import org.eclipse.hawk.timeaware.graph.TimeAwareModelUpdater;
import org.eclipse.hawk.timeaware.queries.TimeAwareEOLQueryEngine;
import org.eclipse.hawk.timeaware.queries.TimelineEOLQueryEngine;
import org.junit.Before;

/**
 * Base class for all time-aware model indexing tests.
 */
public abstract class AbstractTimeAwareModelIndexingTest extends ModelIndexingTest {

	public static final String TREE_MM_PATH = "resources/metamodels/Tree.ecore";

	protected final TreeFactory treeFactory = TreeFactory.eINSTANCE;

	protected ResourceSet rsTree;
	protected TimeAwareEOLQueryEngine timeAwareQueryEngine;
	protected TimelineEOLQueryEngine timelineQueryEngine;

	public AbstractTimeAwareModelIndexingTest(File baseDir, IGraphDatabaseFactory dbFactory, IModelSupportFactory msFactory) {
		super(baseDir, dbFactory, msFactory);
	}

	@Before
	public void setUp() throws Exception {
		indexer.registerMetamodels(new File(baseDir, "resources/metamodels/Ecore.ecore"));
		indexer.registerMetamodels(new File(baseDir, "resources/metamodels/XMLType.ecore"));
		setUpMetamodels();
	
		rsTree = new ResourceSetImpl();
		rsTree.getResourceFactoryRegistry()
			.getExtensionToFactoryMap()
			.put("*", new XMIResourceFactoryImpl());
	
		timeAwareQueryEngine = new TimeAwareEOLQueryEngine();
		indexer.addQueryEngine(timeAwareQueryEngine);
	
		timelineQueryEngine = new TimelineEOLQueryEngine();
		indexer.addQueryEngine(timelineQueryEngine);
	}

	/**
	 * Sets up additional metamodels, beyond the base Ecore and XMLType ones.
	 */
	protected abstract void setUpMetamodels() throws Exception;

	@Override
	protected GraphModelUpdater createModelUpdater() {
		return new TimeAwareModelUpdater();
	}

	@Override
	protected IModelIndexer createIndexer(File indexerFolder, FileBasedCredentialsStore credStore) {
		return new TimeAwareIndexer("test", indexerFolder, credStore, console);
	}

	protected void requestSVNIndex(final TemporarySVNRepository svnRepository) throws Exception {
		final SvnManager vcs = new SvnManager();
		vcs.init(svnRepository.getRepositoryURL().toString(), indexer);
		vcs.run();
		indexer.addVCSManager(vcs, true);
	}

	protected Object timeAwareEOL(final String eolQuery) throws InvalidQueryException, QueryExecutionException {
		return timeAwareEOL(eolQuery, null);
	}

	protected Object timeAwareEOLInRepository(final String eolQuery, TemporarySVNRepository svnRepository) throws InvalidQueryException, QueryExecutionException {
		return timeAwareEOL(eolQuery,
				Collections.singletonMap(
					EOLQueryEngine.PROPERTY_REPOSITORYCONTEXT,
					svnRepository.getRepositoryURL().toString()));
	}

	protected Object timeAwareEOL(final String eolQuery, Map<String, Object> context) throws InvalidQueryException, QueryExecutionException {
		return timeAwareQueryEngine.query(indexer, eolQuery, context);
	}

	protected Object timeAwareEOL(final String eolQuery, final String argumentName, final Object argumentValue) throws InvalidQueryException, QueryExecutionException {
		return timeAwareEOL(eolQuery,
			Collections.singletonMap(EOLQueryEngine.PROPERTY_ARGUMENTS,
				Collections.singletonMap(argumentName, argumentValue)));		
	}

	protected Object timelineEOL(final String eolQuery) throws InvalidQueryException, QueryExecutionException {
		return timelineQueryEngine.query(indexer, eolQuery, null);
	}

}