/**
 * Copyright 2009-2012 OpenAIRE PROJECT (Bielefeld University)
 * Original author: Marek Imialek <marek.imialek at uni-bielefeld.de>
 *
 * Licensed 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 eu.dnetlib.data.udm.is;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException;
import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService;

/**
 * The Class ISInteractions is responsible for getting different  
 * profile information from IS.
 * 
 * @author <a href="mailto:marek.imialek at uni-bielefeld.de">Marek Imialek</a>
 */
public class ISInteractions {

	/** The Constant LOGGER. */
	private static final Logger LOGGER = Logger.getLogger(ISInteractions.class);

	/** The Constant HARVESTING_MDSTORE. */
	public static final String HARVESTING_MDSTORE = "HARVESTING";

	/** The Constant TRANSFORMATION_MDSTORE. */
	public static final String TRANSFORMATION_MDSTORE = "TRANSFORMATION";
	
	/** The look up service. */
	private ISLookUpService lookUpService;
	
	
	/**
	 * Gets the list of repositories from IS registry.
	 * 
	 * @return the repositories list
	 * 
	 * @throws Exception the exception
	 */
	public List<String> getRepositories() throws Exception {

		try {
			LOGGER.debug("Getting list of repositories from IS");
			List<String> repositories;

			repositories = lookUpService.quickSearchProfile(
					"for $x in collection(" +
					"\"/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType\")" +
			" return $x/RESOURCE_PROFILE//RESOURCE_IDENTIFIER/@value/string()");

			if (repositories == null || repositories.size() == 0) {
				String msg = "Can not get the repositories list: "+"for $x in collection(" +
				"\"/db/DRIVER/HarvestingInstanceDSResources/HarvestingInstanceDSResourceType\")" +
				" return $x/RESOURCE_PROFILE//RESOURCE_IDENTIFIER/@value/string()";
				LOGGER.error(msg);
				throw new Exception("Can not get repositories list from IS!");
			} else 
				return repositories;
		} catch (ISLookUpException e) {
			String msg = "Can not get repositories list: "+"for $x in collection(" +
			"\"/db/DRIVER/HarvestingInstanceDSResources/HarvestingInstanceDSResourceType\")" +
			" return $x/RESOURCE_PROFILE//RESOURCE_IDENTIFIER/@value/string() : " + e.getMessage();
			LOGGER.error(msg);
			throw new Exception("Can not get repositories list from IS!");
		}	
	}
	
	/**
	 * Gets the repository identifier.
	 * 
	 * @param repositoryName the repository name
	 * 
	 * @return the repository identifier
	 * 
	 * @throws Exception the exception
	 */
	public String getRepositoryIdentifier (String repositoryName) throws Exception {
		
		String repositoryIdentifier = null;
		
		LOGGER.debug("LookUp for repository Id of "+ repositoryName);
		
		try {
			List<String> repositoryIds = lookUpService.quickSearchProfile(
					"for $x in collection(" +
					"\"/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType\")" +
					" where $x/RESOURCE_PROFILE//ENGLISH_NAME eq " +
					"\""+repositoryName+"\" return $x/RESOURCE_PROFILE//RESOURCE_IDENTIFIER");
			
			if (repositoryIds != null && repositoryIds.size() != 0) {			
				repositoryIdentifier = repositoryIds.get(0);
				repositoryIdentifier = repositoryIdentifier.replace("<RESOURCE_IDENTIFIER value=\"", "");
				repositoryIdentifier = repositoryIdentifier.replace("\"/>", "");
				LOGGER.debug("Repository identifier returned by IS : "+ repositoryIdentifier);
				return repositoryIdentifier;
			} else {
				String msg = "Could not get repository id from IS: "+"for $x in collection(" +
				"\"/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType\")" +
				" where $x/RESOURCE_PROFILE//OFFICIAL_NAME eq " +
				"\""+repositoryName+"\" return $x/RESOURCE_PROFILE//RESOURCE_IDENTIFIER";
				LOGGER.error(msg);
				throw new Exception("Can not find repository ID in IS!");
			}
		} catch(ISLookUpException e) {
			LOGGER.error(e);
			throw new Exception(e);
		}
		
	}
	
	/**
	 * Gets the mdstore identifier for given repository name.
	 * 
	 * @param repositoryId the repository id
	 * @param mdstoreType the mdstore type
	 * 
	 * @return the mD store id
	 * 
	 * @throws Exception the exception
	 */
	public String getMDStoreId(String repositoryId, String mdstoreType) throws Exception {

		String query = null;
		
		if (mdstoreType.equals(TRANSFORMATION_MDSTORE)) {
			query = 
				"for $x in collection(" +
				"\"/db/DRIVER/TransformationDSResources/TransformationDSResourceType\")" +
				" where $x/RESOURCE_PROFILE//REPOSITORY_SERVICE_IDENTIFIER eq " +
				"\""+repositoryId+"\" return $x/RESOURCE_PROFILE//DATA_SINK";
			
		} else if (mdstoreType.equals(HARVESTING_MDSTORE)) {
			query = 
				"for $x in collection(" +
				"\"/db/DRIVER/HarvestingDSResources/HarvestingDSResourceType\")" +
				" where $x/RESOURCE_PROFILE//REPOSITORY_SERVICE_IDENTIFIER eq " +
				"\""+repositoryId+"\" return $x/RESOURCE_PROFILE//DATA_SINK";
		} else {
			LOGGER.error("Wrong mdstore type :"+ mdstoreType);
			throw new Exception("Can not get mdstore identifier for repository: "+ repositoryId);
		}
		
		List<String> mdstoreIds = lookUpService.quickSearchProfile(query);

		if (mdstoreIds != null && mdstoreIds.size() != 0) {
			String mdstoreId = mdstoreIds.get(0);
			String RegEx1 = "\\<DATA_SINK>.*\\<\\/DATA_SINK\\>";
			Pattern pat1 = Pattern.compile(RegEx1);
			Matcher mat1 = pat1.matcher(mdstoreId);

			if (mat1.matches()) {
				mdstoreId = mdstoreId.replace("<DATA_SINK>dnet://MDStoreDS/", "");
				int indexTo = mdstoreId.indexOf("?");
				mdstoreId = mdstoreId.substring(0, indexTo);
				
				LOGGER.debug("MDStore identifier received from IS and extraced: "+ mdstoreId);
				return mdstoreId;
			} else {
				String msg = "MDStore id could not be extracted from: "+ mdstoreId;
				LOGGER.error(msg);
				throw new Exception("Can not get mdstore identifier for repository: "+ repositoryId);
			}
		} else {
			String msg = "Could not get mdstore id from IS: "+ query;
			LOGGER.error(msg);
			throw new Exception("Can not get mdstore identifier for repository: "+ repositoryId);
		}	
	}
	
	/**
	 * Gets the mdstore profile for given mdstore identifier.
	 * 
	 * @param mdstoreId the mdstore id
	 * 
	 * @return the mD store profile
	 * 
	 * @throws Exception the exception
	 */
	public String getMDStoreProfile (String mdstoreId) throws Exception {

		try {
			String mdstoreProfile = lookUpService.getResourceProfile(mdstoreId);
			if (mdstoreProfile != null && !"".equals(mdstoreProfile)) {			
				return mdstoreProfile;
			} else {
				String msg = "Could not get mdstore profile from IS";
				LOGGER.error(msg);
				throw new Exception(msg);
			}
		} catch(ISLookUpException e) {
			LOGGER.error("Exception: " + e);
			throw new Exception(e);
		}  catch(Exception e) {
			LOGGER.error("Exception: " + e);
			throw new Exception(e);
		}
	}

	/**
	 * Sets the look up service.
	 * 
	 * @param lookUpService the lookUpService to set
	 */
	public void setLookUpService(ISLookUpService lookUpService) {
		this.lookUpService = lookUpService;
	}

	/**
	 * Gets the look up service.
	 * 
	 * @return the lookUpService
	 */
	public ISLookUpService getLookUpService() {
		return lookUpService;
	}
}
