package org.gcube.application.geoportal.common.utils;


import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.common.model.rest.DatabaseConnection;
import org.gcube.common.encryption.encrypter.StringEncrypter;
import org.gcube.common.resources.gcore.GenericResource;
import org.gcube.common.resources.gcore.Resource;
import org.gcube.common.resources.gcore.ServiceEndpoint;
import org.gcube.common.resources.gcore.ServiceEndpoint.AccessPoint;
import org.gcube.informationsystem.publisher.RegistryPublisher;
import org.gcube.informationsystem.publisher.RegistryPublisherFactory;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;

import java.util.List;

import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;

public class ISUtils {


	public static DatabaseConnection performQueryForDB(String category, String platform,String flagName, String flag) throws ConfigurationException {

		List<AccessPoint> found=performGetAP(category,platform, flagName,flag);
		if(found.size()>1) {
			throw new ConfigurationException("Multiple SE found ["+found.size()+"] for platform : "+platform+" flag : "+flag);
		}else if (found.isEmpty()){
			throw new ConfigurationException("No SE found for platform : "+platform+" flag : "+flag);
		}
		AccessPoint point=found.get(0);

		DatabaseConnection toReturn=new DatabaseConnection();
		toReturn.setPwd(decryptString(point.password()));
		toReturn.setUser(point.username());
		toReturn.setUrl(point.address());
		return toReturn;

	}


	public static List<AccessPoint> performGetAP(String category,String platform,String flagName,String flagValue) {
		SimpleQuery query = queryFor(ServiceEndpoint.class);

		query.addCondition("$resource/Profile/Category/text() eq '"+category+"'")
		.addCondition("$resource/Profile/Platform/Name/text() eq '"+platform+"'")
		.addCondition("$resource/Profile/AccessPoint//Property[Name/text() eq '"+
				flagName+"'][Value/text() eq '"+flagValue+"']")
		.setResult("$resource/Profile/AccessPoint");

		DiscoveryClient<AccessPoint> client = clientFor(AccessPoint.class);
		return client.submit(query);
	}


	public static List<GenericResource> getGenericResources(String secondaryType,String name) {
		SimpleQuery query = queryFor(GenericResource.class);

		query.addCondition("$resource/Profile/SecondaryType/text() eq '"+secondaryType+"'")
				.addCondition("$resource/Profile/Name/text() eq '"+name+"'");

		DiscoveryClient<GenericResource> client = clientFor(GenericResource.class);
		return client.submit(query);
	}


	public static<T extends Resource> T writeGR(T toRegister) {
		RegistryPublisher rp= RegistryPublisherFactory.create();
		if(toRegister.scopes().isEmpty())
			return rp.create(toRegister);
		else
			return rp.update(toRegister);
	}

	public static String decryptString(String toDecrypt){
		try{
			return StringEncrypter.getEncrypter().decrypt(toDecrypt);
		}catch(Exception e) {
			throw new RuntimeException("Unable to decrypt : "+toDecrypt,e);
		}
	}

	public static String encryptString(String toEncrypt){
		try{
			return StringEncrypter.getEncrypter().encrypt(toEncrypt);
		}catch(Exception e) {
			throw new RuntimeException("Unable to decrypt : "+toEncrypt,e);
		}
	}
}
