package eu.dnetlib.validator2.validation.guideline.openaire.cris;

import eu.dnetlib.validator2.validation.guideline.Builders;
import eu.dnetlib.validator2.validation.guideline.Cardinality;
import eu.dnetlib.validator2.validation.guideline.ElementSpec;
import eu.dnetlib.validator2.validation.guideline.Guideline;
import eu.dnetlib.validator2.validation.utils.RegexValuePredicate;
import org.w3c.dom.Document;

import java.util.Collection;

import static eu.dnetlib.validator2.validation.utils.SupportedRegExs.COMPILED_YYYY_MM_DD_REGEX;

public class CrisPatentV111Profile extends AbstractCrisProfile {

    private static final String[] TYPE_VOCABULARY = { "http://purl.org/coar/resource_type/c_15cd" };

    private static final Builders.ElementSpecBuilder TYPE_SPEC = Builders.
            forMandatoryElement("Type", Cardinality.ONE).
            allowedValues(TYPE_VOCABULARY);

    private static final Builders.ElementSpecBuilder REGISTRATION_DATE_SPEC = Builders.
            forOptionalElement("RegistrationDate").
            allowedValues(new RegexValuePredicate(COMPILED_YYYY_MM_DD_REGEX)); //TODO: Add optional time zone indication in regex

    private static final Builders.ElementSpecBuilder APPROVAL_DATE_SPEC = Builders.
            forOptionalElement("ApprovalDate").
            allowedValues(new RegexValuePredicate(COMPILED_YYYY_MM_DD_REGEX)); //TODO: Add optional time zone indication in regex

    private static final Builders.ElementSpecBuilder COUNTRY_CODE_SPEC = Builders.
            forOptionalElement("CountryCode");

    private static final Builders.ElementSpecBuilder ISSUER_SPEC = Builders.
            forOptionalRepeatableElement("Issuer").
            withSubElement(Builders.
                    forOptionalElement("DisplayName")).
            withSubElement(ORG_UNIT_SPEC); //TODO: Pass proper spec

    private static final Builders.ElementSpecBuilder PATENT_NUMBER_SPEC = Builders.
            forOptionalElement("PatentNumber");

    private static final Builders.ElementSpecBuilder INVENTORS_SPEC = Builders.
            forOptionalElement("Inventors").
            withSubElement(Builders.
                    forOptionalRepeatableElement("Inventor").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    withSubElement(PERSON_SPEC). //TODO: Pass proper spec
                    withSubElement(Builders.
                        forOptionalRepeatableElement("Affiliation")));

    private static final Builders.ElementSpecBuilder HOLDERS_SPEC = Builders.
            forOptionalElement("Holders").
            withSubElement(Builders.
                    forOptionalRepeatableElement("Holder").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (Person or OrgUnit)
                    withSubElement(PERSON_SPEC). //TODO: Pass proper spec
                    withSubElement(ORG_UNIT_SPEC)); //TODO: Pass proper spec

    private static final Builders.ElementSpecBuilder ORIGINATES_FROM_SPEC = Builders.
        forOptionalRepeatableElement("OriginatesFrom").
        //TODO: Optional 1 of (Project or Funding).
        withSubElement(PROJECT_SPEC). //TODO: Pass proper spec
        withSubElement(FUNDING_SPEC); //TODO: Pass proper spec

    private static final Builders.ElementSpecBuilder PREDECESSOR_SPEC = Builders.
            forOptionalRepeatableElement("Predecessor").
            withSubElement(null); //TODO: Pass self spec

    private static final Builders.ElementSpecBuilder REFERENCES_SPEC = Builders.
            forOptionalRepeatableElement("References").
            //TODO: Optional 1 of 3 (Publication, Patent, Product)
            withSubElement(PUBLICATION_SPEC). //TODO: Pass proper spec
            withSubElement(null). //TODO: Pass self
            withSubElement(PRODUCT_SPEC); //TODO: Pass proper spec

    private static final ElementSpec PATENT_SPEC = Builders.
            forMandatoryElement("Patent", Cardinality.ONE).
            withMandatoryAttribute("id").
            withSubElement(TYPE_SPEC).
            withSubElement(TITLE_SPEC).
            withSubElement(VERSION_INFO_SPEC).
            withSubElement(REGISTRATION_DATE_SPEC).
            withSubElement(APPROVAL_DATE_SPEC).
            withSubElement(COUNTRY_CODE_SPEC).
            withSubElement(ISSUER_SPEC).
            withSubElement(PATENT_NUMBER_SPEC).
            withSubElement(INVENTORS_SPEC).
            withSubElement(HOLDERS_SPEC).
            withSubElement(ABSTRACT_SPEC).
            withSubElement(SUBJECT_SPEC).
            withSubElement(KEYWORD_SPEC).
            withSubElement(ORIGINATES_FROM_SPEC).
            withSubElement(PREDECESSOR_SPEC).
            withSubElement(REFERENCES_SPEC).
            build();

    public CrisPatentV111Profile() {
        super("OpenAIRE Guidelines for Patent element of CRIS Managers v1.1.1");
    }

    @Override
    public Collection<? extends Guideline<Document>> guidelines() {
        return null;
    }

    @Override
    public Guideline<Document> guideline(String guidelineName) {
        return null;
    }

    @Override
    public int maxScore() {
        return 0;
    }
}
