package eu.dnetlib.wds.parser;

import com.ximpleware.AutoPilot;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
import eu.dnetlib.data.transform.VtdUtilityParser;
import eu.dnetlib.data.transform.VtdUtilityParser.Node;
import eu.dnetlib.miscutils.collections.Pair;
import eu.dnetlib.pid.resolver.model.*;
import eu.dnetlib.pid.resolver.parser.AbstractResolverParser;
import eu.dnetlib.wds.resolver.WDSObjectRelation;
import eu.dnetlib.wds.resolver.WDSResolvedObject;

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

/**
 * Created by sandro on 9/13/16.
 */
public class PMFResolverParser extends AbstractResolverParser {

    @Override
    public ResolvedObject parseObject(final String record) {
        try {
            final WDSResolvedObject parsedObject = new WDSResolvedObject();
            final VTDGen vg = new VTDGen();
            vg.setDoc(record.getBytes());
            vg.parse(true);

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

            ap.declareXPathNameSpace("dri", "http://www.driver-repository.eu/namespace/dri");

            final String resolvedDate = VtdUtilityParser.getSingleValue(ap, vn, "//dri:resolvedDate");


            ap.declareXPathNameSpace("oaf", "http://namespace.dnet.eu/oaf");
            final List<Node> pid = VtdUtilityParser.getTextValuesWithAttributes(ap, vn, "//oaf:pid", Arrays.asList("type"));

            if (pid != null && pid.size() > 0) {
                final String currentPid = pid.get(0).getTextValue();
                final String currentPidType = pid.get(0).getAttributes().get("type");
                parsedObject.setPid(currentPid);
                parsedObject.setPidType(currentPidType);
            } else {
                return null;
            }

            List<Node> collectedFromNodes =
                    VtdUtilityParser.getTextValuesWithAttributes(ap, vn, "//oaf:collectedFrom", Arrays.asList("name", "id", "mode", "completionStatus"));


            List<Node> relatedIdentifiers =
                    VtdUtilityParser.getTextValuesWithAttributes(ap, vn, "//oaf:relatedIdentifier",
                            Arrays.asList("relatedIdentifierType", "relationType", "entityType", "inverseRelationType"));

            if (relatedIdentifiers != null && relatedIdentifiers.size() > 0) {
                final List<ObjectRelation> relations = new ArrayList<>();
                relatedIdentifiers.forEach(relation -> {
                    final String currentPid = relation.getTextValue();
                    final String currentPidType = relation.getAttributes().get("relatedIdentifierType");
                    final String currentType = relation.getAttributes().get("entityType");
                    final WDSObjectRelation currentRelation = new WDSObjectRelation();
                    currentRelation.setTargetPID(inferPid(new PID(currentPid, currentPidType)));
                    currentRelation.setSourcePID(inferPid(new PID(parsedObject.getPid(), parsedObject.getPidType())));
                    currentRelation.setRelationSemantics(relation.getAttributes().get("relationType"));
                    currentRelation.setInverseRelation(relation.getAttributes().get("inverseRelationType"));


                    currentRelation.setTargetType(ObjectType.valueOf(currentType));
//					if (parsedObject.getDatasourceProvenance() != null && parsedObject.getDatasourceProvenance().size() > 0) {
//                        final DLIObjectProvenance provenance = parsedObject.getDatasourceProvenance().get(0);
//
//                        final DLIObjectProvenance newProvenance = new DLIObjectProvenance();
//                        newProvenance.setCompletionStatus(CompletionStatus.incomplete.toString());
//						newProvenance.setDatasourceId(provenance.getDatasourceId());
//						newProvenance.setDatasource(provenance.getDatasource());
//						newProvenance.setProvisionMode(provenance.getProvisionMode());
//						currentRelation.setRelationProvenance(Arrays.asList(newProvenance));
//					}

                    relations.add(currentRelation);
                });
                parsedObject.setRelations(relations);
            }

            ap.declareXPathNameSpace("dc", "http://purl.org/dc/elements/1.1/");
            final List<String> authorsNode = VtdUtilityParser.getTextValue(ap, vn, "//dc:creator");
            parsedObject.setAuthors(authorsNode);
            parsedObject.setTitles(VtdUtilityParser.getTextValue(ap, vn, "//dc:title"));


            parsedObject.addDescription(new Pair<>("unknown", VtdUtilityParser.getSingleValue(ap, vn, "//dc:description")));

            parsedObject.addDate("unknown", VtdUtilityParser.getSingleValue(ap, vn, "//dc:date"));
            List<Node> subjects = VtdUtilityParser.getTextValuesWithAttributes(ap, vn, "//dc:subject", Arrays.asList("scheme"));
            if (subjects != null && subjects.size() > 0) {
                final List<SubjectType> currentSubjects = new ArrayList<>();
                subjects.forEach(it -> {

                    String scheme = it.getAttributes().get("scheme");
                    if (scheme == null)
                        scheme = "unknown";
                    currentSubjects.add(new SubjectType(scheme, it.getTextValue()));
                });

                parsedObject.setSubjects(currentSubjects);
            }

            setType(parsedObject, VtdUtilityParser.getSingleValue(ap, vn, "//dc:type"));

            return parsedObject;
        } catch (Throwable e) {
            log.debug("Input record: " + record);
            log.error("Error on parsing record ", e);
            return null;
        }

    }
}
