package eu.dnetlib.index.action;

import java.io.StringReader;
import java.util.List;

import eu.dnetlib.enabling.locators.UniqueServiceLocator;
import eu.dnetlib.enabling.tools.blackboard.BlackboardJob;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerAction;
import eu.dnetlib.enabling.tools.blackboard.BlackboardServerHandler;
import eu.dnetlib.index.IndexServerDAO;
import eu.dnetlib.index.IndexServerDAOMap;
import eu.dnetlib.rmi.enabling.ISLookUpService;
import eu.dnetlib.rmi.provision.IndexServiceException;
import eu.dnetlib.utils.MetadataReference;
import eu.dnetlib.utils.MetadataReferenceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Created by sandro on 10/25/16.
 */
public class RefreshMDFormatAction extends AbstractIndexAction implements BlackboardServerAction<IndexAction> {

	private static final Log log = LogFactory.getLog(RefreshMDFormatAction.class); // NOPMD by marko on 11/24/08 5:02 PM

	private final transient ThreadLocal<SAXReader> domFactory = new ThreadLocal<SAXReader>() {

		@Override
		protected SAXReader initialValue() {
			return new SAXReader();
		}
	};

	@Autowired
	private transient MetadataReferenceFactory mdFactory;
	@Autowired
	private IndexServerDAOMap indexServerDAOMap;

	@Autowired
	private UniqueServiceLocator serviceLocator;

	@Override
	public void execute(final BlackboardServerHandler handler, final BlackboardJob job) throws Exception {

		final String profileId = job.getParameters().get("profileId");
		if (profileId == null) {
			handler.failed(job, new IndexServiceException("parameter profile Id missing"));
			return;
		}

		try {

			final String profile = serviceLocator.getService(ISLookUpService.class).getResourceProfile(profileId);
			final Document doc = parse(profile);
			final Node formatNode = doc.selectSingleNode("//CONFIGURATION/NAME/text()");

			if ((formatNode != null) && !formatNode.asXML().isEmpty()) {

				final String format = formatNode.asXML();
				final Iterable<Element> layouts = (Iterable<Element>) doc.selectNodes("//STATUS/LAYOUTS/LAYOUT");

				final Node interpretationNode = doc.selectSingleNode("//CONFIGURATION/INTERPRETATION/text()");
				final String interpretation = interpretationNode.asXML();

				log.info("found a change in mdFormat: " + format);
				for (Element element : layouts) {
					final String layout = element.attributeValue("name");

					// updates index schema based on mdFormat and layout
					final MetadataReference mdRef = mdFactory.getMetadata(format, layout, interpretation);
					final Document fields = parse(element.selectSingleNode("./FIELDS").asXML());

					List<String> backends = serviceTools.getBackendIds(mdRef);

					if ((backends == null) || backends.isEmpty()) {
						log.warn("There is no backendId in profiles for mdref " + mdRef);
					}

					for (String backendId : backends) {
						IndexServerDAO idxDao = indexServerDAOMap.getIndexServerDAO(backendId);
						if (idxDao == null) throw new RuntimeException("No index found for the mdformat " + mdRef);
						log.info("Found index DAO which serve this mdFormat");
						idxDao.updateIndexCollection(mdRef, fields);
					}
				}
			}
			log.info("Upload schema completed");
		} catch (Exception e) {
			handler.failed(job, new IndexServiceException(e));
			return;
		}
		handler.done(job);
	}

	/**
	 * Helper method, parses an xml string.
	 *
	 * @param source the xml.
	 * @return the parsed xml.
	 * @throws DocumentException could happen
	 */
	private Document parse(final String source) throws DocumentException {
		return domFactory.get().read(new StringReader(source));
	}
}
