package eu.dnetlib.functionality.index.utils;

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

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;
import org.springframework.beans.factory.annotation.Autowired;
import org.xml.sax.InputSource;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.mycila.xmltool.CallBack;
import com.mycila.xmltool.XMLDoc;
import com.mycila.xmltool.XMLTag;

import eu.dnetlib.data.provision.index.rmi.IndexServiceException;
import eu.dnetlib.functionality.index.client.IndexClientException;

public class MDFormatReader {

	static class XmlUtils {

		/**
		 * helper method, parses a list of fields.
		 *
		 * @param fields
		 *            the given fields
		 * @return the parsed fields
		 * @throws IndexServiceException
		 *             if cannot parse the fields
		 */
		public static Document parse(final String xml) {
			try {
				return new SAXReader().read(new StringReader(xml));
			} catch (DocumentException e) {
				throw new IllegalArgumentException("cannot parse: " + xml);
			}
		}

		public static InputSource asInputSource(final String input) throws DocumentException {
			return new InputSource(new StringReader(parse(input).asXML()));
		}
	}

	@Autowired
	private ServiceTools serviceTools;

	@Autowired
	private MetadataReferenceFactory mdFactory;

	public List<MetadataReference> listMDRefs() throws IndexClientException {
		return serviceTools.listMDRefs();
	}

	public Document getFields(final MetadataReference mdRef) {
		String fields = serviceTools.getIndexFields(mdRef);
		return (fields != null) && !fields.isEmpty() ? XmlUtils.parse(fields) : null;
	}

	public Map<String, String> getAttributeMap(final MetadataReference mdRef, final String attribute) throws IndexClientException {
		return getAttributeTable(mdRef, attribute).column(attribute);
	}

	public Table<String, String, String> getAttributeTable(final MetadataReference mdRef, final String... attributeList) throws IndexClientException {

		final String fields = serviceTools.getIndexFields(mdRef);
		if (fields.isEmpty()) throw new IndexClientException("No result getting index layout informations");
		final Table<String, String, String> t = HashBasedTable.create();
		XMLDoc.from(serviceTools.getIndexFields(mdRef), false).forEach("//FIELD", new CallBack() {

			@Override
			public void execute(final XMLTag field) {

				for (String attribute : attributeList) {
					String value = null;

					if ("xpath".equals(attribute)) {
						if (!(field.hasAttribute("xpath") || field.hasAttribute("value"))) return;

						value = field.hasAttribute("xpath") ? field.getAttribute("xpath") : field.getAttribute("value");
					}

					if ("weight".equals(attribute)) {
						if (!(field.hasAttribute(attribute))) return;

						value = field.hasAttribute(attribute) ? field.getAttribute(attribute) : "";
					}

					if (value == null) {
						value = field.getAttribute(attribute);
					}

					t.put(field.getAttribute("name").toLowerCase(), attribute, value);
				}
			}
		});
		return t;
	}

}
