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

import eu.dnetlib.validator2.engine.Status
import eu.dnetlib.validator2.engine.XMLHelper
import eu.dnetlib.validator2.validation.guideline.Guideline
import eu.dnetlib.validator2.validation.guideline.SyntheticGuideline
import org.w3c.dom.Document
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Unroll

class LiteratureGuidelinesV3ProfileSpecification extends Specification {

    @Shared LiteratureGuidelinesV3Profile profile = new LiteratureGuidelinesV3Profile()

    static final RECORD_21811 = "Record_21811.xml"
    static final RECORD_62524 = "Record_62524.xml"
    static final RECORD_ALL_VALID = "v3Literature_all_valid_guidelines_record.xml"
    static final RECORD_ALL_INVALID = "v3Literature_no_valid_guidelines_record.xml"

    @Shared Document doc21811 = XMLHelper.parse("/openaireguidelinesV3/dia.library.tuc.gr/$RECORD_21811")
    @Shared Document doc62524 = XMLHelper.parse("/openaireguidelinesV3/dia.library.tuc.gr/$RECORD_62524")
    @Shared Document docAllValid = XMLHelper.parse("/openaireguidelinesV3/$RECORD_ALL_VALID")
    @Shared Document docAllInvalid = XMLHelper.parse("/openaireguidelinesV3/$RECORD_ALL_INVALID")

    @Unroll
    def "Profile returns proper guideline by name #guidelineName"() {
        when:
        def guideLine = profile.guideline(guidelineName)

        then:
        guideLine == expectedGuideline

        where:
        guidelineName            || expectedGuideline
        "Title"                  || LiteratureGuidelinesV3Profile.TITLE
        "Creator"                || LiteratureGuidelinesV3Profile.CREATOR
        "Project Identifier"     || LiteratureGuidelinesV3Profile.PROJECT_IDENTIFIER
        "Access Level"           || LiteratureGuidelinesV3Profile.ACCESS_LEVEL
        "License Condition"      || LiteratureGuidelinesV3Profile.LICENSE_CONDITION
        "Embargo End Date"       || LiteratureGuidelinesV3Profile.EMBARGO_END_DATE
        "Alternative Identifier" || LiteratureGuidelinesV3Profile.ALTERNATIVE_IDENTIFIER
        "Publication Reference"  || LiteratureGuidelinesV3Profile.PUBLICATION_REFERENCE
        "Dataset Reference"      || LiteratureGuidelinesV3Profile.DATASET_REFERENCE
        "Subject"                || LiteratureGuidelinesV3Profile.SUBJECT
        "Description"            || LiteratureGuidelinesV3Profile.DESCRIPTION
        "Publisher"              || LiteratureGuidelinesV3Profile.PUBLISHER
        "Contributor"            || LiteratureGuidelinesV3Profile.CONTRIBUTOR
        "Publication Date"       || LiteratureGuidelinesV3Profile.PUBLICATION_DATE
        "Publication Type M"     || LiteratureGuidelinesV3Profile.PUBLICATION_TYPE_MANDATORY
        "Publication Type O"     || LiteratureGuidelinesV3Profile.PUBLICATION_TYPE_OPTIONAL
        "Publication Version"    || LiteratureGuidelinesV3Profile.PUBLICATION_VERSION
        "Format"                 || LiteratureGuidelinesV3Profile.FORMAT
        "Resource Identifier"    || LiteratureGuidelinesV3Profile.RESOURCE_IDENTIFIER
        "Source"                 || LiteratureGuidelinesV3Profile.SOURCE
        "Language"               || LiteratureGuidelinesV3Profile.LANGUAGE
        "Relation"               || LiteratureGuidelinesV3Profile.RELATION
        "Coverage"               || LiteratureGuidelinesV3Profile.COVERAGE
        "Audience"               || LiteratureGuidelinesV3Profile.AUDIENCE
    }

    @Unroll
    def "#guidelineName against #record results in STATUS: #expectedStatus, SCORE: #expectedScore, ERRORS: #expectedErrors, WARNINGS: #expectedWarnings, internalError: #internalErr"() {
        given:
        SyntheticGuideline guideLine = profile.guideline(guidelineName)

        when:
        Guideline.Result result = guideLine.validate(doc)

        then:
        printResultErrorsAndWarnings(result)
        verifyAll(result) {
            status() == expectedStatus
            score() == expectedScore
            errors().size() == expectedErrors
            warnings().size() == expectedWarnings
            internalError() == null
        }

        where:

        record             | doc           | guidelineName            || expectedStatus | expectedScore                             | expectedErrors | expectedWarnings

        RECORD_ALL_VALID   | docAllValid   | "Title"                  || Status.SUCCESS | profile.TITLE.weight                      | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Creator"                || Status.SUCCESS | profile.CREATOR.weight                    | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Project Identifier"     || Status.SUCCESS | profile.PROJECT_IDENTIFIER.weight         | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Access Level"           || Status.SUCCESS | profile.ACCESS_LEVEL.weight               | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "License Condition"      || Status.SUCCESS | profile.LICENSE_CONDITION.weight          | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Embargo End Date"       || Status.SUCCESS | profile.EMBARGO_END_DATE.weight           | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Alternative Identifier" || Status.SUCCESS | profile.ALTERNATIVE_IDENTIFIER.weight     | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publication Reference"  || Status.SUCCESS | profile.PUBLICATION_REFERENCE.weight      | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Dataset Reference"      || Status.SUCCESS | profile.DATASET_REFERENCE.weight          | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Subject"                || Status.SUCCESS | profile.SUBJECT.weight                    | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Description"            || Status.SUCCESS | profile.DESCRIPTION.weight                | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publisher"              || Status.SUCCESS | profile.PUBLISHER.weight                  | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Contributor"            || Status.SUCCESS | profile.CONTRIBUTOR.weight                | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publication Date"       || Status.SUCCESS | profile.PUBLICATION_DATE.weight           | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publication Type M"     || Status.SUCCESS | profile.PUBLICATION_TYPE_MANDATORY.weight | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publication Type O"     || Status.SUCCESS | profile.PUBLICATION_TYPE_OPTIONAL.weight  | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Publication Version"    || Status.SUCCESS | profile.PUBLICATION_VERSION.weight        | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Format"                 || Status.SUCCESS | profile.FORMAT.weight                     | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Resource Identifier"    || Status.SUCCESS | profile.RESOURCE_IDENTIFIER.weight        | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Source"                 || Status.SUCCESS | profile.SOURCE.weight                     | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Language"               || Status.SUCCESS | profile.LANGUAGE.weight                   | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Relation"               || Status.SUCCESS | profile.RELATION.weight                   | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Coverage"               || Status.SUCCESS | profile.COVERAGE.weight                   | 0              | 0
        RECORD_ALL_VALID   | docAllValid   | "Audience"               || Status.SUCCESS | profile.AUDIENCE.weight                   | 0              | 0

        RECORD_ALL_INVALID | docAllInvalid | "Title"                  || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "Creator"                || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "Project Identifier"     || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Access Level"           || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "License Condition"      || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Embargo End Date"       || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Alternative Identifier" || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Publication Reference"  || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Dataset Reference"      || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Subject"                || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Description"            || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Publisher"              || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Contributor"            || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Publication Date"       || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "Publication Type M"     || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "Publication Type O"     || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Publication Version"    || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Format"                 || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Resource Identifier"    || Status.FAILURE | 0                     | 1             | 0
        RECORD_ALL_INVALID | docAllInvalid | "Source"                 || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Language"               || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Relation"               || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Coverage"               || Status.SUCCESS | 0                     | 0             | 1
        RECORD_ALL_INVALID | docAllInvalid | "Audience"               || Status.SUCCESS | 0                     | 0             | 1

        RECORD_21811       | doc21811      | "Title"                  || Status.SUCCESS | profile.TITLE.weight                      | 0         | 0
        RECORD_21811       | doc21811      | "Creator"                || Status.SUCCESS | profile.CREATOR.weight                    | 0         | 0
        RECORD_21811       | doc21811      | "Project Identifier"     || Status.SUCCESS | profile.PROJECT_IDENTIFIER.weight         | 0         | 0
        RECORD_21811       | doc21811      | "Access Level"           || Status.SUCCESS | profile.ACCESS_LEVEL.weight               | 0         | 0
        RECORD_21811       | doc21811      | "License Condition"      || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Embargo End Date"       || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Alternative Identifier" || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Publication Reference"  || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Dataset Reference"      || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Subject"                || Status.SUCCESS | profile.SUBJECT.weight                    | 0         | 0
        RECORD_21811       | doc21811      | "Description"            || Status.SUCCESS | profile.DESCRIPTION.weight                | 0         | 0
        RECORD_21811       | doc21811      | "Publisher"              || Status.SUCCESS | profile.PUBLISHER.weight                  | 0         | 0
        RECORD_21811       | doc21811      | "Contributor"            || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Publication Date"       || Status.FAILURE | 0                                         | 1         | 0
        RECORD_21811       | doc21811      | "Publication Type M"     || Status.SUCCESS | profile.PUBLICATION_TYPE_MANDATORY.weight | 0         | 0
        RECORD_21811       | doc21811      | "Publication Type O"     || Status.SUCCESS | profile.PUBLICATION_TYPE_OPTIONAL.weight  | 0         | 0
        RECORD_21811       | doc21811      | "Publication Version"    || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Format"                 || Status.SUCCESS | profile.FORMAT.weight                     | 0         | 0
        RECORD_21811       | doc21811      | "Resource Identifier"    || Status.SUCCESS | profile.RESOURCE_IDENTIFIER.weight        | 0         | 0
        RECORD_21811       | doc21811      | "Source"                 || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Language"               || Status.SUCCESS | profile.LANGUAGE.weight                   | 0         | 0
        RECORD_21811       | doc21811      | "Relation"               || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Coverage"               || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_21811       | doc21811      | "Audience"               || Status.SUCCESS | 0                                         | 0         | 1

        RECORD_62524       | doc62524      | "Title"                  || Status.FAILURE | 0                                         | 1         | 0
        RECORD_62524       | doc62524      | "Creator"                || Status.SUCCESS | profile.CREATOR.weight                    | 0         | 0
        RECORD_62524       | doc62524      | "Project Identifier"     || Status.SUCCESS | profile.PROJECT_IDENTIFIER.weight         | 0         | 0
        RECORD_62524       | doc62524      | "Access Level"           || Status.SUCCESS | profile.ACCESS_LEVEL.weight               | 0         | 0
        RECORD_62524       | doc62524      | "License Condition"      || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Embargo End Date"       || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Alternative Identifier" || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Publication Reference"  || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Dataset Reference"      || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Subject"                || Status.SUCCESS | profile.SUBJECT.weight                    | 0         | 0
        RECORD_62524       | doc62524      | "Description"            || Status.SUCCESS | profile.DESCRIPTION.weight                | 0         | 0
        RECORD_62524       | doc62524      | "Publisher"              || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Contributor"            || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Publication Date"       || Status.FAILURE | 0                                         | 1         | 0
        RECORD_62524       | doc62524      | "Publication Type M"     || Status.SUCCESS | profile.PUBLICATION_TYPE_MANDATORY.weight | 0         | 0
        RECORD_62524       | doc62524      | "Publication Type O"     || Status.SUCCESS | profile.PUBLICATION_TYPE_OPTIONAL.weight  | 0         | 0
        RECORD_62524       | doc62524      | "Publication Version"    || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Format"                 || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Resource Identifier"    || Status.SUCCESS | profile.RESOURCE_IDENTIFIER.weight        | 0         | 0
        RECORD_62524       | doc62524      | "Source"                 || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Language"               || Status.SUCCESS | profile.LANGUAGE.weight                   | 0         | 0
        RECORD_62524       | doc62524      | "Relation"               || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Coverage"               || Status.SUCCESS | 0                                         | 0         | 1
        RECORD_62524       | doc62524      | "Audience"               || Status.SUCCESS | 0                                         | 0         | 1
    }

    //Helper for easier evaluation
    void printResultErrorsAndWarnings(result) {
        if (!result.errors().isEmpty()) {
            println "Result errors:"
            for (String error : result.errors()) {
                println error
            }
        } else println "Result contains no errors"

        if (!result.warnings().isEmpty()) {
            println "Result warnings:"
            for (String warning : result.warnings()) {
                println warning
            }
        } else println "Result contains no warnings"

        if (result.internalError() != null) println "Internal error occured: ${result.internalError()}"
    }

}
