package eu.dnetlib.data.mdstore.modular;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import eu.dnetlib.data.mdstore.DocumentNotFoundException;
import eu.dnetlib.data.mdstore.MDStoreService;
import eu.dnetlib.data.mdstore.MDStoreServiceException;
import eu.dnetlib.enabling.resultset.IterableResultSetFactory;
import eu.dnetlib.enabling.tools.AbstractBaseService;
import eu.dnetlib.enabling.tools.blackboard.NotificationHandler;
import org.springframework.beans.factory.annotation.Required;

import javax.xml.ws.wsaddressing.W3CEndpointReference;
import java.util.List;
import java.util.Map;

public class ModularMDStoreService extends AbstractBaseService implements MDStoreService {

	/**
	 * notification handler.
	 */
	private NotificationHandler notificationHandler;

	private MDStoreFeeder feeder;

	private MDStoreRetriever retriever;

	private IterableResultSetFactory iterableResultSetFactory;


    public List<String> getMDStoreRecords(final String mdId, final int pageSize, final int offset, final Map<String, String> queryParam) throws MDStoreServiceException {

        return retriever.getMDStoreRecords(mdId, pageSize, offset, queryParam);

    }

	@Override
	public W3CEndpointReference deliverMDRecords(final String mdId, final String from, final String until, final String recordFilter)
			throws MDStoreServiceException {
		return retriever.deliver(mdId, from, until, recordFilter);
	}

	@Override
	public W3CEndpointReference bulkDeliverMDRecords(final String format, final String layout, final String interpretation) throws MDStoreServiceException {
		return getIterableResultSetFactory().createIterableResultSet(retriever.deliver(format, layout, interpretation));
	}

	@Override
	public String deliverRecord(final String mdId, final String recordId) throws MDStoreServiceException, DocumentNotFoundException {
		return retriever.deliverRecord(mdId, recordId);
	}

	@Override
	public List<String> getListOfMDStores() throws MDStoreServiceException {
		return (Lists.transform(retriever.getDao().listMDStores(), new Function<MDStoreDescription, String>() {

			@Override
			public String apply(final MDStoreDescription input) {
				return input.getId();
			}
		}));
	}

	@Override
	public List<String> listMDStores(final String format, final String layout, final String interpretation) throws MDStoreServiceException {
		return retriever.getDao().listMDStores(format, layout, interpretation);
	}

	@Override
	public void notify(final String subscriptionId, final String topic, final String isId, final String message) {
		getNotificationHandler().notified(subscriptionId, topic, isId, message);
	}

	@Override
	public boolean storeMDRecordsFromRS(final String mdId, final String rsId, final String storingType) throws MDStoreServiceException {
		throw new MDStoreServiceException("not implemented, use the Blackboard asynchronous equivalent");
	}

	@Override
	public int size(final String mdId) throws MDStoreServiceException {
		return this.getRetriever().getDao().getCachedSize(mdId);
	}

	@Override
	public int size(final String format, final String layout, final String interpretation) throws MDStoreServiceException {
		return this.getRetriever().getDao().getSumOfSizes(format, layout, interpretation);
	}

	public NotificationHandler getNotificationHandler() {
		return notificationHandler;
	}

	@Required
	public void setNotificationHandler(final NotificationHandler notificationHandler) {
		this.notificationHandler = notificationHandler;
	}

	public MDStoreFeeder getFeeder() {
		return feeder;
	}

	public void setFeeder(final MDStoreFeeder feeder) {
		this.feeder = feeder;
	}

	public MDStoreRetriever getRetriever() {
		return retriever;
	}

	public void setRetriever(final MDStoreRetriever retriever) {
		this.retriever = retriever;
	}

	public IterableResultSetFactory getIterableResultSetFactory() {
		return iterableResultSetFactory;
	}

	@Required
	public void setIterableResultSetFactory(final IterableResultSetFactory iterableResultSetFactory) {
		this.iterableResultSetFactory = iterableResultSetFactory;
	}

}
