package org.gcube.application.geoportal.service.engine.providers;

import lombok.extern.slf4j.Slf4j;
import org.gcube.application.cms.caches.AbstractScopedMap;
import org.gcube.application.cms.implementations.ISInterface;
import org.gcube.application.cms.implementations.ImplementationProvider;
import org.gcube.application.geoportal.common.model.configuration.MongoConnection;
import org.gcube.application.geoportal.common.model.rest.ConfigurationException;
import org.gcube.application.geoportal.service.ServiceConstants;
import org.gcube.application.geoportal.service.model.internal.db.Mongo;
import org.gcube.common.resources.gcore.ServiceEndpoint;

import java.util.List;
import java.util.Map;

@Slf4j
public class MongoClientProvider extends AbstractScopedMap<Mongo> {

	public MongoClientProvider() {
		super("MongoClient cache");
		//NO TTL = Map by context
//		setTTL(Duration.of(10, ChronoUnit.MINUTES));
	}

	@Override
	protected Mongo retrieveObject(String context) throws ConfigurationException {
		MongoConnection conn=performQueryForMongoDB(ImplementationProvider.get().
                        getProvidedObjectByClass(ISInterface.class),
				ServiceConstants.SE_GNA_DB_CATEGORY,
				ServiceConstants.MONGO_SE_PLATFORM,
				ServiceConstants.SE_GNA_DB_FLAG,
				ServiceConstants.MONGO_SE_GNA_FLAG);

		log.debug("Connecting to "+conn);
		 return new Mongo(conn);
	}
	
	@Override
	protected void dispose(Mongo toDispose) {
		toDispose.close();
	}
	

	private static MongoConnection performQueryForMongoDB(ISInterface is,String category, String platform,String flagName, String flagValue) throws ConfigurationException {

		List<ServiceEndpoint.AccessPoint> found=is.performGetAP(category,platform,flagName, flagValue);
		if(found.size()>1) {
			throw new ConfigurationException("Multiple SE found ["+found.size()+"] for platform : "+platform+" flag : "+flagValue);
		}else if (found.isEmpty()){
			throw new ConfigurationException("No SE found for platform : "+platform+" flag : "+flagValue);
		}
		ServiceEndpoint.AccessPoint point=found.get(0);
		MongoConnection toReturn=new MongoConnection();
		for(ServiceEndpoint.Property prop:point.properties()) {
			switch(prop.name()) {
				case "host" : {
					toReturn.getHosts().add(prop.value());
					break;}
			}
		}
		toReturn.getHosts().add(point.address());
		Map<String, ServiceEndpoint.Property> props=point.propertyMap();
		toReturn.setDatabase(props.get("database").value());
		toReturn.setPassword(is.decryptString(point.password()));
		toReturn.setPort(Integer.parseInt(props.get("port").value()));
		toReturn.setUser(point.username());

		return toReturn;
	}
}
