package eu.dnetlib.resolver.parser;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.ximpleware.AutoPilot;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
import eu.dnetlib.data.transform.VtdUtilityParser;
import eu.dnetlib.dli.DLIUtils;
import eu.dnetlib.dli.resolver.model.*;

import eu.dnetlib.pid.resolver.model.ObjectProvenance;
import eu.dnetlib.pid.resolver.model.ObjectRelation;
import eu.dnetlib.pid.resolver.model.ObjectType;
import eu.dnetlib.pid.resolver.model.PID;
import eu.dnetlib.pid.resolver.parser.AbstractResolverParser;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Created by sandro on 9/29/16.
 */
public class ScholixResolverParser extends AbstractResolverParser {

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

	@Override
    public DLIResolvedObject parseObject(final String record) {

		try {
            final DLIResolvedObject parsedObject = new DLIResolvedObject();
            final VTDGen vg = new VTDGen();
			vg.setDoc(record.getBytes());
			vg.parse(true);

			final VTDNav vn = vg.getNav();
			final AutoPilot ap = new AutoPilot(vn);


            final String resolvedDate = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='resolvedDate']");
            parsedObject.setResolvedDate(resolvedDate);




			final String completionStatus = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='completionStatus']");


			List<VtdUtilityParser.Node> provenances =
					VtdUtilityParser.getTextValuesWithAttributes(ap, vn, "//*[local-name()='collectedFrom']", Arrays.asList("completionStatus", "id", "name"));




            String sourcePid = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='identifier']/*[local-name()='identifier']");
            String sourcePidTye = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='identifier']/*[local-name()='schema']");
            if (DLIUtils.isValidDoi(sourcePid)!= null) {
                sourcePid = DLIUtils.isValidDoi(sourcePid);
                sourcePidTye = "doi";
            }


            final String sourceType = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='objectType']/*[local-name()='type']");

            final String sourcePublisherId = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='publisher']//*[local-name()='identifier']");
            final String sourcePublisher = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='publisher']/*[local-name()='name']");


            if (StringUtils.isEmpty(sourcePid) || StringUtils.isEmpty(sourcePidTye)) {
                return null;
            }

            final List<ObjectProvenance> provenanceList = new ArrayList<>();
            if (provenances != null) {
				provenances.forEach(it -> {
                    final DLIObjectProvenance provenance = new DLIObjectProvenance();
                    provenance.setDatasourceId(it.getAttributes().get("id"));
					provenance.setDatasource(it.getAttributes().get("name"));
					provenance.setCompletionStatus(it.getAttributes().get("completionStatus"));
                    provenance.setPublisher(sourcePublisher);
                    provenance.setPublisherId(sourcePublisherId);
                    provenance.setProvisionMode("collected");
					provenanceList.add(provenance);

				});
			}


			parsedObject.setDatasourceProvenance(provenanceList);

			parsedObject.setCompletionStatus(completionStatus);

            parsedObject.setPid(sourcePid);
            parsedObject.setPidType(sourcePidTye);
            if (!StringUtils.isEmpty(sourceType))
                parsedObject.setType(ObjectType.valueOf(sourceType));

            final String sourceTitle = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='source']/*[local-name()='title']");

            final List<String> creators = VtdUtilityParser.getTextValue(ap, vn, "//*[local-name()='source']//*[local-name()='creatorName']");

            if (!StringUtils.isEmpty(sourceTitle))
                parsedObject.setTitles(Arrays.asList(sourceTitle));
            if (creators != null) {
                final List<String> sourceCreators = new ArrayList<>();

                creators.forEach(
                        agent -> {
                            if (!StringUtils.isEmpty(agent)) {
                                sourceCreators.add(agent);
                            }
                        }
                );
                parsedObject.setAuthors(sourceCreators);
            }

            parsedObject.setDate(VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='link']/*[local-name()='publicationDate']"));

            String targetPid = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='target']/*[local-name()='identifier']/*[local-name()='identifier']");
            String targetPidTye = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='target']/*[local-name()='identifier']/*[local-name()='schema']");
            if (DLIUtils.isValidDoi(targetPid)!= null) {
                targetPid = DLIUtils.isValidDoi(targetPid);
                targetPidTye = "doi";
            }
            final String targetType = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='target']/*[local-name()='objectType']/*[local-name()='type']");


            if (StringUtils.isEmpty(targetPid) || StringUtils.isEmpty(targetPidTye)) {
                return null;
			}


            final String relationType = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='relashionship']/*[local-name()='name']");
            final String inverseRelationSemantic = VtdUtilityParser.getSingleValue(ap, vn, "//*[local-name()='relashionship']/*[local-name()='inverseRelashionship']");


            final List<ObjectRelation> relations = new ArrayList<>();

            DLIObjectRelation relation = new DLIObjectRelation();
            relation.setCompletionStatus(CompletionStatus.incomplete.toString());
			relation.setRelationProvenance(parsedObject.getDatasourceProvenance());
            relation.setRelationSemantics(relationType);
            relation.setInverseRelation(inverseRelationSemantic);
            relation.setTargetPID(new PID(targetPid, targetPidTye));
            if (!StringUtils.isEmpty(targetType))
                relation.setTargetType(ObjectType.valueOf(targetType));
            relations.add(relation);
			parsedObject.setRelations(relations);

			return parsedObject;
		} catch (Throwable e) {
			log.info("Error on parsing", e);
		}
		return null;
	}
}
