package eu.dnetlib.openaire.api;

import javax.annotation.Resource;

import com.google.common.base.Function;
import com.google.gson.Gson;
import eu.dnetlib.data.index.CloudIndexClient;
import eu.dnetlib.data.index.CloudIndexClientFactory;
import eu.dnetlib.enabling.locators.UniqueServiceLocator;

import eu.dnetlib.miscutils.functional.xml.ApplyXslt;
import eu.dnetlib.msro.workflows.nodes.index.OafToIndexRecordFactory;
import eu.dnetlib.openaire.api.objects.PublicationEntry;
import eu.dnetlib.rmi.enabling.ISLookUpService;
import eu.dnetlib.rmi.manager.MSROException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

/**
 * Created by michele on 11/11/15.
 */
@Controller
public class SinglePublicationSubmitter {

	@Value(value = "oaf.schema.location")
	private String oafSchemaLocation;

	@Resource
	private UniqueServiceLocator serviceLocator;

	@Resource
	private OafToIndexRecordFactory oafToIndexRecordFactory;

	@Resource
	private RecentPublicationsQueue recentPublicationsQueue;

	@Resource(name = "openaireplusApisVelocityEngine")
	private VelocityEngine velocityEngine;

	@Value(value = "${openaireplus.msro.api.findSolrIndexUrl.xquery}")
	private ClassPathResource findSolrIndexUrl;

	@Value(value = "${openaireplus.msro.api.findIndexDsInfo.xquery}")
	private ClassPathResource findIndexDsInfo;

	@RequestMapping(value = "/api/publications/feedJson", method = RequestMethod.POST)
	public
	@ResponseBody
	boolean addPublication(@RequestParam(value = "json", required = true) final String json) throws MSROException {
		final PublicationEntry pub = new Gson().fromJson(json, PublicationEntry.class);
		return addPublication(pub);
	}

	@RequestMapping(value = "/api/publications/feedObject", method = RequestMethod.POST)
	public
	@ResponseBody
	boolean addPublication(@RequestBody final PublicationEntry pub) throws MSROException {

		if (StringUtils.isBlank(pub.getOriginalId())) {
			throw new MSROException("A required field is missing: originalId");
		}
		if (StringUtils.isBlank(pub.getTitle())) {
			throw new MSROException("A required field is missing: title");
		}
		if (StringUtils.isBlank(pub.getUrl())) {
			throw new MSROException("A required field is missing: url");
		}
		if (StringUtils.isBlank(pub.getLicenseCode())) {
			throw new MSROException("A required field is missing: licenceCode");
		}
		if (StringUtils.isBlank(pub.getResourceType())) {
			throw new MSROException("A required field is missing: resourceType");
		}
		if (StringUtils.isBlank(pub.getCollectedFromId())) {
			throw new MSROException("A required field is missing: collectedFromId");
		}

		/*if (StringUtils.isBlank(pub.getHostedById())) {
			throw new MSROException("A required field is missing: hostedById");
		}*/

		CloudIndexClient idxClient = null;

		try {
			final String baseUrl = calculateIndexBaseUrl();
			final String[] arr = calculateCurrentIndexDsInfo().split("@@@");
			final String indexDsId = arr[0].trim();
			final String format = arr[1].trim();
			final String coll = arr[2].trim();

			idxClient = CloudIndexClientFactory.newIndexClient(baseUrl, coll, false);

			final String oafRecord = pub.asOafRecord(velocityEngine, serviceLocator.getService(ISLookUpService.class), oafSchemaLocation);

			recentPublicationsQueue.add(oafRecord);

			//TODO check runtime works
			final Function<String, String> xslt = (Function<String, String>) oafToIndexRecordFactory.newTransformer(format);
			return (idxClient.feed(oafRecord, indexDsId, xslt) == 0);
		} catch (Throwable e) {
			throw new MSROException("Error adding publication: " + e.getMessage(), e);
		} finally {
			if (idxClient != null) {
				idxClient.close();
			}
		}
	}

	private String calculateCurrentIndexDsInfo() throws Exception {
		final String query = IOUtils.toString(findIndexDsInfo.getInputStream());
		return serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(query);
	}

	private String calculateIndexBaseUrl() throws Exception {
		final String query = IOUtils.toString(findSolrIndexUrl.getInputStream());
		return serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(query);
	}

}
