package eu.dnetlib.enabling.datasources;

import java.io.StringReader;
import java.util.function.Function;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import eu.dnetlib.clients.dsManager.DatasourceDesc;
import eu.dnetlib.clients.dsManager.IfaceDesc;
import eu.dnetlib.miscutils.datetime.DateUtils;

public class ProfileToDatasourceDesc implements Function<String, DatasourceDesc> {

	private static final Log log = LogFactory.getLog(ProfileToDatasourceDesc.class);

	public static DatasourceDesc convert(final String profile) throws Exception {
		final SAXReader reader = new SAXReader();
		final Document doc = reader.read(new StringReader(profile));

		final DatasourceDesc ds = new DatasourceDesc();
		ds.setId(doc.valueOf("//RESOURCE_IDENTIFIER/@value"));
		ds.setDatasourceClass(doc.valueOf("//DATASOURCE_TYPE"));
		ds.setTypology(doc.valueOf("//TYPOLOGY"));
		ds.setOfficialName(doc.valueOf("//OFFICIAL_NAME"));
		ds.setEnglishName(doc.valueOf("//ENGLISH_NAME"));
		ds.setCountryCode(doc.valueOf("//COUNTRY"));
		ds.setLongitude(NumberUtils.toDouble(doc.valueOf("//LOCATION/LONGITUDE"), 0.0));
		ds.setLatitude(NumberUtils.toDouble(doc.valueOf("//LOCATION/LATITUDE"), 0.0));
		ds.setTimezone(NumberUtils.toDouble(doc.valueOf("//LOCATION/TIMEZONE"), 0.0));
		ds.setWebsiteUrl(doc.valueOf("//REPOSITORY_WEBPAGE"));
		ds.setOrganization(doc.valueOf("//REPOSITORY_INSTITUTION"));
		ds.setContactEmail(doc.valueOf("//ADMIN_INFO"));

		for (final Object o : doc.selectNodes("//INTERFACES/INTERFACE")) {
			final Element n = (Element) o;

			final IfaceDesc ifc = new IfaceDesc();

			ifc.setId(n.valueOf("@id"));
			ifc.setCompliance(n.valueOf("@compliance"));
			ifc.setTypology(n.valueOf("@typology"));
			ifc.setContentDescription(n.valueOf("@contentDescription"));
			ifc.setActive(BooleanUtils.toBoolean(n.valueOf("@active")));
			ifc.setRemovable(BooleanUtils.toBoolean(n.valueOf("@removable")));
			ifc.setBaseUrl(n.valueOf("./BASE_URL"));
			ifc.setAccessProtocol(n.valueOf("./ACCESS_PROTOCOL"));

			for (final Object o1 : n.selectNodes("./ACCESS_PROTOCOL/@*")) {
				final Node attr = (Node) o1;
				ifc.getAccessParams().put(attr.getName(), attr.getText());
			}
			for (final Object o1 : n.selectNodes("./INTERFACE_EXTRA_FIELD")) {
				final Node f = (Node) o1;
				ifc.getExtraFields().put(f.valueOf("@name"), f.getText());
			}

			ds.getInterfaces().add(ifc);
		}

		final DateUtils dateUtils = new DateUtils();
		for (final Object o : doc.selectNodes("//EXTRA_FIELDS/EXTRA_FIELD")) {
			final String k = ((Element) o).valueOf("./key").trim();
			final String v = ((Element) o).valueOf("./value").trim();

			if (k.equalsIgnoreCase("ACTIVATION_ID")) {
				ds.setActivationId(v);
			} else if (k.equalsIgnoreCase("NamespacePrefix")) {
				ds.setNamespacePrefix(v);
			} else if (k.equalsIgnoreCase("aggregatorName")) {
				ds.setAggregator(v);
			} else if (k.equalsIgnoreCase("dateOfCollection")) {
				ds.setDateOfCollection(dateUtils.parse(v));
			} else if (k.equalsIgnoreCase("dateOfValidation")) {
				ds.setDateOfValidation(dateUtils.parse(v));
			}
		}

		return ds;
	}

	@Override
	public DatasourceDesc apply(final String profile) {
		try {
			return ProfileToDatasourceDesc.convert(profile);
		} catch (final Exception e) {
			log.error("Error convering profile", e);
			return null;
		}
	}
}
