/*
 * Hibernate Search, full-text search for your domain model
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.search.test.integration;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;

/**
 * Helper class for integration testing of the JBoss Modules generated by the
 * hibernate-search-modules Maven module.
 *
 * The slot version is set as a property in the parent pom, and passed to the JVM
 * of Arquillian as a system property of the Maven maven-failsafe-plugin.
 *
 * @since 5.0
 */
public class VersionTestHelper {

	private static String hibernateSearchVersion = null;
	private static String hibernateSearchVersionBuiltIn = null;
	private static String hibernateSearchModuleSlot = null;
	private static String hibernateOrmModuleName = null;
	private static String luceneFullVersion = null;
	private static String hibernateAnnotationsFullVersion = null;

	private VersionTestHelper() {
		//not meant to be created
	}

	/**
	 * @return the slot version of the Hibernate Search modules generated by this project
	 */
	public static synchronized String getModuleSlotString() {
		if ( hibernateSearchModuleSlot == null ) {
			hibernateSearchModuleSlot = injectVariables( "${test.hibernate.search.module.slot}" );
			if ( hibernateSearchModuleSlot == null || hibernateSearchModuleSlot.isEmpty() ) {
				String versionHibernateSearch = getDependencyVersionHibernateSearch();
				String[] split = versionHibernateSearch.split( "\\." );
				hibernateSearchModuleSlot = split[0] + '.' + split[1];
			}
		}
		return hibernateSearchModuleSlot;
	}

	public static synchronized String getDependencyVersionHibernateSearch() {
		if ( hibernateSearchVersion == null ) {
			hibernateSearchVersion = injectVariables( "${dependency.version.HibernateSearch}" );
		}
		return hibernateSearchVersion;
	}

	public static synchronized String getHibernateORMModuleName() {
		if ( hibernateOrmModuleName == null ) {
			hibernateOrmModuleName = "org.hibernate:" + injectVariables( "${hibernate-orm.module.slot}" );
		}
		return hibernateOrmModuleName;
	}

	public static synchronized String getDependencyVersionHibernateSearchBuiltIn() {
		if ( hibernateSearchVersionBuiltIn == null ) {
			hibernateSearchVersionBuiltIn = injectVariables( "${dependency.version.HibernateSearch.builtin}" );
			// if no built-in version is specified, default to the version from Maven
			if ( hibernateSearchVersionBuiltIn == null
					|| hibernateSearchVersionBuiltIn.isEmpty()
					|| hibernateSearchVersionBuiltIn.startsWith( "${" ) ) {
				hibernateSearchVersionBuiltIn = getDependencyVersionHibernateSearch();
			}
		}
		return hibernateSearchVersionBuiltIn;
	}

	public static synchronized String getDependencyVersionLucene() {
		if ( luceneFullVersion == null ) {
			luceneFullVersion = injectVariables( "${dependency.version.Lucene}" );
		}
		return luceneFullVersion;
	}

	public static synchronized String getDependencyVersionHibernateCommonsAnnotations() {
		if ( hibernateAnnotationsFullVersion == null ) {
			hibernateAnnotationsFullVersion = injectVariables( "${dependency.version.hcann}" );
		}
		return hibernateAnnotationsFullVersion;
	}

	public static String getWildFlyModuleIdentifier() {
		return "org.hibernate.search.orm:" + getModuleSlotString();
	}

	public static String injectVariables(String inputString) {
		Properties projectCompilationProperties = new Properties();
		final InputStream resourceAsStream = VersionTestHelper.class.getClassLoader().getResourceAsStream( "module-versions.properties" );
		try {
			projectCompilationProperties.load( resourceAsStream );
		}
		catch (IOException e) {
			throw new RuntimeException( e );
		}
		finally {
			try {
				resourceAsStream.close();
			}
			catch (IOException e) {
				throw new RuntimeException( e );
			}
		}
		Set<Entry<Object,Object>> entrySet = projectCompilationProperties.entrySet();
		for ( Entry<Object,Object> entry : entrySet ) {
			String key = (String) entry.getKey();
			String value = (String) entry.getValue();
			inputString = inputString.replace( "${" + key + "}", value );
		}
		return inputString;
	}

}
