package eu.dnetlib.enabling.resultset;

import java.util.List;

import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.springframework.beans.factory.annotation.Required;

import com.google.common.collect.Lists;

import eu.dnetlib.enabling.resultset.rmi.ResultSetException;
import eu.dnetlib.enabling.resultset.rmi.ResultSetService;
import eu.dnetlib.enabling.tools.ServiceResolver;
import eu.dnetlib.miscutils.collections.MappedCollection;
import eu.dnetlib.miscutils.functional.UnaryFunction;

/**
 * A resultset filter. Applies a transformation for every resultset record.
 *
 * @author marko
 *
 */
public class MappedResultSet implements ResultSetListener {

	/**
	 * input resultset.
	 */
	private ResultSetService resultSet;

	/**
	 * input resultset id.
	 */
	private String rsId;

	/**
	 * mapper function.
	 */
	private UnaryFunction<String, String> mapper;

	/**
	 * service resolver.
	 */
	private ServiceResolver serviceResolver;

	/**
	 * Create a new mapped resultset.
	 *
	 * @param epr input resultset epr
	 * @param mapper mapper function
	 * @param serviceResolver service resolver
	 */
	public MappedResultSet(final W3CEndpointReference epr, final UnaryFunction<String, String> mapper, final ServiceResolver serviceResolver) {
		super();

		this.resultSet = serviceResolver.getService(ResultSetService.class, epr);
		this.rsId = serviceResolver.getResourceIdentifier(epr);

		this.mapper = mapper;

		this.serviceResolver = serviceResolver;
	}

	/**
	 * {@inheritDoc}
	 *
	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getResult(int, int)
	 */
	public List<String> getResult(final int fromPosition, final int toPosition) {
		try {
			final List<String> source = resultSet.getResult(rsId, fromPosition, toPosition, "waiting");
			return Lists.newArrayList(new MappedCollection<String, String>(source, mapper));
		} catch (final ResultSetException e) {
			throw new IllegalStateException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 * @see eu.dnetlib.enabling.resultset.ResultSetListener#getSize()
	 */
	public int getSize() {
		try {
			return resultSet.getNumberOfElements(rsId);
		} catch (final ResultSetException e) {
			throw new IllegalStateException(e);
		}
	}

	public ResultSetService getResultSet() {
		return resultSet;
	}

	public void setResultSet(final ResultSetService resultSet) {
		this.resultSet = resultSet;
	}

	public String getRsId() {
		return rsId;
	}

	public void setRsId(final String rsId) {
		this.rsId = rsId;
	}

	public UnaryFunction<String, String> getMapper() {
		return mapper;
	}

	public void setMapper(final UnaryFunction<String, String> mapper) {
		this.mapper = mapper;
	}

	public ServiceResolver getServiceResolver() {
		return serviceResolver;
	}

	@Required
	public void setServiceResolver(final ServiceResolver serviceResolver) {
		this.serviceResolver = serviceResolver;
	}

}
