package eu.dnetlib.dli.proto;

import eu.dnetlib.data.graph.model.DNGFRelDecoder;
import eu.dnetlib.data.proto.*;
import eu.dnetlib.data.proto.DliProtos;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Set;
import java.util.stream.Collectors;

import static eu.dnetlib.data.proto.dli.Scholix2ObjectProtos.*;
import static eu.dnetlib.data.proto.DNGFProtos.*;

public class DNGF2Scholix2Converter {
    public static Scholix.Builder  withSource(final DNGFEntity input) {
        return Scholix.newBuilder().setSource(asScholixResource(input));
    }

    private static ScholixResource asScholixResource(DNGFEntity input) {
        final ScholixResource.Builder resource = ScholixResource.newBuilder();

        //Set publication date to today
        final LocalDateTime now = LocalDateTime.now();
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        resource.setPublicationDate(now.format(formatter));

        //set identifier
        final FieldTypeProtos.StructuredProperty pid = input.getExtension(DliProtos.typedIdentifier).stream().findFirst().get();
        resource.setIdentifier(ScholixIdentifier.newBuilder().setID(pid.getValue()).setIDScheme(pid.getQualifier().getClassid()).build());


        //Set All creator
        resource.addAllCreator(DngfDliUtils.parseAuthor(input)
                .stream()
                .map(a -> ScholixAuthor.newBuilder().setName(a).build())
                .collect(Collectors.toList()));

        switch (input.getType()) {
            case publication: {
                resource.setType(ScholixObjectType.newBuilder().setName("literature").build());
                final PublicationProtos.Publication.Metadata pm = input.getPublication().getMetadata();
                if (pm.getTitleCount() > 0) {
                    resource.setTitle(pm.getTitleList().stream()
                            .map(FieldTypeProtos.StructuredProperty::getValue)
                            .findFirst().get());
                }
                resource.setPublicationDate(pm.getDateofacceptance().getValue());
                final Set<String> publishers = DngfDliUtils.parsePublishers(input);
                if (publishers != null) {
                    publishers.forEach(publisher -> resource.addPublisher(ScholixEntityId.newBuilder().setName(publisher)));
                }
                break;
            }
            case dataset: {
                resource.setType(ScholixObjectType.newBuilder().setName("dataset").build());
                final DatasetProtos.Dataset.Metadata dm = input.getDataset().getMetadata();
                if (dm.getTitleCount() > 0) {
                    resource.setTitle(dm.getTitleList().stream()
                            .map(FieldTypeProtos.StructuredProperty::getValue)
                            .findFirst().get());
                }

                resource.setPublicationDate(dm.getDateofacceptance().getValue());
                final Set<String> publishers = DngfDliUtils.parsePublishers(input);
                if (publishers != null) {
                    publishers.forEach(publisher -> resource.addPublisher(ScholixEntityId.newBuilder().setName(publisher)));
                }
                break;
            }
            case unknown:
                resource.setType(ScholixObjectType.newBuilder().setName("unknown").build());
                break;
            case datasource:
            case organization:
            case person:
            case project:
                throw new IllegalArgumentException("cannot transform type: " + input.getType());
        }
        return resource.build();
    }

    public static Scholix.Builder withTarget(final DNGFEntity input, final DNGFRel rel) {

        final LocalDateTime now = LocalDateTime.now();
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        final Scholix.Builder scholix = Scholix.newBuilder()
                .setTarget(asScholixResource(input))
                .setRelationshipType(ScholixRelationship.newBuilder()
                        .setName(mapRelationship(DNGFRelDecoder.decode(rel).getRelClass()))
                        .setSubType(DNGFRelDecoder.decode(rel).getRelClass())
                        .setSubTypeSchema("datacite")
                )
                .setLinkPublicationDate(now.format(formatter))
                .addAllLinkProvider(rel.getCollectedfromList()
                        .stream()
                        .map(cf ->
                                ScholixEntityId.newBuilder()
                                        .setName(cf.getValue())
                                        .addIdentifier(
                                                ScholixIdentifier.newBuilder()
                                                        .setIDScheme("dnetIdentifier")
                                                        .setID(cf.getKey()))
                                        .build())
                        .collect(Collectors.toList()));
        return scholix;
    }

    private static String mapRelationship(final String original) {
        if (original == null) {
            return "IsRelatedTo";
        }
        switch (original.toLowerCase().trim()){
            case  "issupplementto":
                return "IsSupplementTo";
            case "issupplementedby":
                return "IsSupplementedBy";
            case "references":
                return "References";
            case "isreferencedby":
                return "IsReferencedBy";
            default:
                return "IsRelatedTo";
        }
    }

}
