package eu.dnetlib.msro.workflows.nodes.download;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import com.google.common.base.Function;
import com.google.gson.Gson;

import eu.dnetlib.data.download.rmi.DownloadItem;

// TODO: Auto-generated Javadoc
/**
 * The Class UrlExtractor.
 */
public class UrlExtractor implements Function<String, String> {

	/** The Constant log. */
	private static final Log log = LogFactory.getLog(UrlExtractor.class);

	/** The xpath url. */
	private String xpathURL;

	/** The xpath. */
	private String xpathMetadataID;

	/** The xpath open access. */
	private String xpathOpenAccess;

	/** The xpath embargo date. */
	private String xpathEmbargoDate;

	/**
	 * Instantiates a new url extractor.
	 *
	 * @param xpath
	 *            the xpath
	 * @param xpathMetadataID
	 *            the xpath metadata id
	 */
	public UrlExtractor(final String xpath, final String xpathMetadataID, final String xpathOpenAccess, final String xpathEmbargoDate) {
		this.xpathURL = xpath;
		this.xpathMetadataID = xpathMetadataID;
		this.xpathOpenAccess = xpathOpenAccess;
		this.xpathEmbargoDate = xpathEmbargoDate;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see com.google.common.base.Function#apply(java.lang.Object)
	 */
	@Override
	public String apply(final String input) {
		try {
			DownloadItem di = new DownloadItem();
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder;
			builder = factory.newDocumentBuilder();
			if (input == null) {
				log.error("Metadata input is null");
				return null;
			}
			Document doc = builder.parse(new ByteArrayInputStream(input.getBytes()));
			XPathFactory xPathFactory = XPathFactory.newInstance();
			XPath myXpath = xPathFactory.newXPath();
			XPathExpression expression = myXpath.compile(xpathURL);
			Object values = expression.evaluate(doc, XPathConstants.NODESET);
			di.setUrl(getNodes((NodeList) values));
			di.setOriginalUrl(getNodes((NodeList) values));

			if (xpathOpenAccess != null) {
				expression = myXpath.compile(xpathOpenAccess);
				String openAccess = expression.evaluate(doc);
				di.setOpenAccess(openAccess);
			}
			if (xpathEmbargoDate != null) {
				expression = myXpath.compile(xpathEmbargoDate);
				String embargoDate = expression.evaluate(doc);
				if (!StringUtils.isEmpty(embargoDate)) {
					try {
						DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");
						DateTime dt = fmt.parseDateTime(embargoDate);
						di.setEmbargoDate(dt.toDate());
					} catch (Exception pe) {}
				}
			}
			expression = myXpath.compile(xpathMetadataID);
			String extracted_metadataId = expression.evaluate(doc);
			di.setIdItemMetadata(extracted_metadataId);
			return di.toJSON();
		} catch (Exception e) {
			log.error("OPSSS... Something bad happen on evaluating ", e);
			return null;
		}

	}

	/**
	 * Gets the nodes.
	 *
	 * @param nodes
	 *            the nodes
	 * @return the nodes
	 */
	private String getNodes(final NodeList nodes) {
		List<String> extracted_Url = new ArrayList<String>();
		if (nodes != null) {
			for (int i = 0; i < nodes.getLength(); i++) {
				extracted_Url.add(nodes.item(i).getNodeValue());
			}
		}
		return new Gson().toJson(extracted_Url);
	}

	/**
	 * Gets the xpath metadata id.
	 *
	 * @return the xpathMetadataID
	 */
	public String getXpathMetadataID() {
		return xpathMetadataID;
	}

	/**
	 * Sets the xpath metadata id.
	 *
	 * @param xpathMetadataID
	 *            the xpathMetadataID to set
	 */
	public void setXpathMetadataID(final String xpathMetadataID) {
		this.xpathMetadataID = xpathMetadataID;
	}

	/**
	 * Gets the xpath url.
	 *
	 * @return the xpath url
	 */
	public String getXpathURL() {
		return xpathURL;
	}

	/**
	 * Sets the xpath url.
	 *
	 * @param xpathURL
	 *            the new xpath url
	 */
	public void setXpathURL(final String xpathURL) {
		this.xpathURL = xpathURL;
	}

	/**
	 * Gets the xpath open access.
	 *
	 * @return the xpath open access
	 */
	public String getXpathOpenAccess() {
		return xpathOpenAccess;
	}

	/**
	 * Sets the xpath open access.
	 *
	 * @param xpathOpenAccess
	 *            the new xpath open access
	 */
	public void setXpathOpenAccess(final String xpathOpenAccess) {
		this.xpathOpenAccess = xpathOpenAccess;
	}

	/**
	 * Gets the xpath embargo date.
	 *
	 * @return the xpath embargo date
	 */
	public String getXpathEmbargoDate() {
		return xpathEmbargoDate;
	}

	/**
	 * Sets the xpath embargo date.
	 *
	 * @param xpathEmbargoDate
	 *            the new xpath embargo date
	 */
	public void setXpathEmbargoDate(final String xpathEmbargoDate) {
		this.xpathEmbargoDate = xpathEmbargoDate;
	}

}
