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 org.w3c.dom.Document;

import java.util.Collection;

public class CrisProjectV111Profile extends AbstractCrisProfile {

    private static final Builders.ElementSpecBuilder TYPE_SPEC = Builders.
            forOptionalRepeatableElement("Type").
            withMandatoryAttribute("scheme");

    private static final Builders.ElementSpecBuilder CONSORTIUM_SPEC = Builders.
            forOptionalElement("Consortium").
            // All 5 sub-elements have the same structure. A method could be extracted here.
            withSubElement(Builders.
                    forOptionalRepeatableElement("Coordinator").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)). //TODO: Pass proper spec
            withSubElement(Builders.
                    forOptionalRepeatableElement("Partner").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)). //TODO: Pass proper spec
            withSubElement(Builders.
                    forOptionalRepeatableElement("Contractor").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)). //TODO: Pass proper spec
            withSubElement(Builders.
                    forOptionalRepeatableElement("InKindContractor").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)). //TODO: Pass proper spec
            withSubElement(Builders.
                    forOptionalRepeatableElement("Member").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)); //TODO: Pass proper spec

    private static final Builders.ElementSpecBuilder TEAM_SPEC = Builders.
            forOptionalElement("Team").
            // All 3 sub-elements have the same structure. A method could be extracted here.
            withSubElement(Builders.
                    forOptionalRepeatableElement("PrincipalInvestigator").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    withSubElement(PERSON_SPEC). //TODO: Pass proper spec
                    withSubElement(Builders.
                            forOptionalRepeatableElement("Affiliation"))).
            withSubElement(Builders.
                    forOptionalRepeatableElement("Contact").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    withSubElement(PERSON_SPEC). //TODO: Pass proper spec
                    withSubElement(Builders.
                            forOptionalRepeatableElement("Affiliation"))).
            withSubElement(Builders.
                    forOptionalRepeatableElement("Member").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    withSubElement(PERSON_SPEC). //TODO: Pass proper spec
                    withSubElement(Builders.
                            forOptionalRepeatableElement("Affiliation")));

    private static final Builders.ElementSpecBuilder FUNDED_SPEC = Builders.
            forOptionalRepeatableElement("Funded").
            withSubElement(Builders.
                    forOptionalElement("By").
                    withSubElement(Builders.
                            forOptionalElement("DisplayName")).
                    //TODO: Optional 1 of 2 (OrgUnit, Person)
                    withSubElement(ORG_UNIT_SPEC). //TODO: Pass proper spec
                    withSubElement(PERSON_SPEC)). //TODO: Pass proper spec
            withSubElement(Builders.
                    forOptionalElement("As").
                    withSubElement(FUNDING_SPEC)); //TODO: Pass proper spec

    private static final Builders.ElementSpecBuilder USES_SPEC = Builders.
            forOptionalRepeatableElement("Uses").
            withSubElement(EQUIPMENT_SPEC); //TODO: Pass proper spec

    private static final ElementSpec PROJECT_SPEC = Builders.
            forMandatoryElement("Project", Cardinality.ONE).
            withMandatoryAttribute("id").
            withSubElement(TYPE_SPEC).
            withSubElement(ACRONYM_SPEC).
            withSubElement(TITLE_SPEC).
            withSubElement(IDENTIFIER_SPEC).
            withSubElement(START_DATE_SPEC).
            withSubElement(END_DATE_SPEC).
            withSubElement(CONSORTIUM_SPEC).
            withSubElement(TEAM_SPEC).
            withSubElement(FUNDED_SPEC).
            withSubElement(SUBJECT_SPEC).
            withSubElement(KEYWORD_SPEC).
            withSubElement(ABSTRACT_SPEC).
            withSubElement(STATUS_SPEC).
            withSubElement(USES_SPEC).
            withSubElement(OA_MANDATE_SPEC).
            build();

    public CrisProjectV111Profile() {
        super("OpenAIRE Guidelines for OrgUnit 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;
    }
}
