package eu.dnetlib.data.utility.objectpackaging;

import java.io.ByteArrayInputStream;
import java.io.StringReader;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.ws.wsaddressing.W3CEndpointReference;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

import eu.dnetlib.data.utility.objectpackaging.rmi.ObjectPackagingException;

public class ObjectQueue extends AbstractQueue {

	private String xpathID;

	protected ObjectQueue(W3CEndpointReference epr, String xpathID, ObjectProviderFactory objectProviderFactory) throws ObjectPackagingException {
		super(epr, objectProviderFactory);
		this.xpathID = xpathID;
	}

	public String watchNextElementId() throws ObjectPackagingException {
		String elem = watchNextElement();
		if (elem == null) {
			return null;
		}
		return calculateID(elem);
	}

	private String calculateID(String s) throws ObjectPackagingException {
		// hack
		if (s.contains("objIdentifier")) {
			return fastCalculateID(s);
		}
		return slowCalculateID(s);
	}

	private String fastCalculateID(String s) throws ObjectPackagingException {
		try {
			XMLInputFactory factory = XMLInputFactory.newInstance();
			XMLStreamReader parser = factory.createXMLStreamReader(new ByteArrayInputStream(s.getBytes()));
			while (parser.hasNext()) {
				int event = parser.nextTag();
				if (event == XMLStreamConstants.START_ELEMENT && "objIdentifier".equals(parser.getLocalName())) {
					parser.next();
					return parser.getText();
				}
			}
			throw new ObjectPackagingException("xpath " + xpathID + " has returned an empty identifier");
		} catch (XMLStreamException e) {
			throw new IllegalStateException(e);
		}

	}

	private String slowCalculateID(String s) throws ObjectPackagingException {
		try {
			SAXReader reader = new SAXReader();
			Document doc = reader.read(new StringReader(s));

			String res = doc.valueOf(xpathID);
			if ((res == null) || (res.length() == 0)) {
				throw new ObjectPackagingException("xpath " + xpathID + " has returned an empty identifier");
			}
			return res;
		} catch (DocumentException e) {
			throw new ObjectPackagingException(e);
		}
	}

}
