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 LiteratureGuidelinesV4ProfileSpecification extends Specification {

    static final RECORD_ALL_VALID = "v4_literature_all_guidelines_record.xml"
    static final RECORD_ALL_INVALID = "v4_literature_all_invalid_guidelines_record.xml"
    static final MEDIA_REP_2534 = "oai_mediarep_org_doc_2534.xml"

    @Shared LiteratureGuidelinesV4Profile profile = new LiteratureGuidelinesV4Profile()

    @Shared Document docAllValid = XMLHelper.parse("/openaireguidelinesV4/$RECORD_ALL_VALID")
    @Shared Document docAllInvalid = XMLHelper.parse("/openaireguidelinesV4/$RECORD_ALL_INVALID")
    @Shared Document docMediaRep2534 = XMLHelper.parse("/openaireguidelinesV4/$MEDIA_REP_2534")

    @Unroll
    def "#guidelineName against #record results in STATUS: #expectedStatus, SCORE: #expectedScore, ERRORS: #expectedErrors, WARNINGS: #expectedWarnings, internalError: null"() {
        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              | 1
        RECORD_ALL_VALID   | docAllValid     | "Creator"                   || Status.SUCCESS | profile.CREATOR.weight                   | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Contributor"               || Status.SUCCESS | profile.CONTRIBUTOR.weight               | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Funding Reference"         || Status.SUCCESS | profile.FUNDING_REFERENCE.weight         | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Alternate Identifier"      || Status.SUCCESS | profile.ALTERNATE_IDENTIFIER.weight      | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Related Identifier"        || Status.SUCCESS | profile.RELATED_IDENTIFIER.weight        | 0              | 3   // 4 warnings - 1 unwanted for resourceTypeGeneral Attribute //TODO: Incomplete spec. See TODO in RELATED_IDENTIFIER_SPEC - LiteratureGuidelinesV4Profile line:210
        RECORD_ALL_VALID   | docAllValid     | "Embargo Period Date"       || Status.SUCCESS | profile.EMBARGO_PERIOD_DATE.weight       | 0              | 0   // 1 error - possibly connected to Publication Date
        RECORD_ALL_VALID   | docAllValid     | "Language"                  || Status.SUCCESS | profile.LANGUAGE.weight                  | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Publisher"                 || Status.SUCCESS | profile.PUBLISHER.weight                 | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Publication Date"          || Status.SUCCESS | profile.PUBLICATION_DATE.weight          | 0              | 0   // 1 error - possibly connected to Embargo Period Date
        RECORD_ALL_VALID   | docAllValid     | "Resource Type"             || Status.SUCCESS | profile.RESOURCE_TYPE.weight             | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Description"               || Status.SUCCESS | profile.DESCRIPTION.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     | "Access Rights"             || Status.SUCCESS | profile.ACCESS_RIGHTS.weight             | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Source"                    || Status.SUCCESS | profile.SOURCE.weight                    | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Subject"                   || Status.SUCCESS | profile.SUBJECT.weight                   | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "License Condition"         || Status.SUCCESS | profile.LICENSE_CONDITION.weight         | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Coverage"                  || Status.SUCCESS | profile.COVERAGE.weight                  | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Size"                      || Status.SUCCESS | profile.SIZE.weight                      | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Geo Location"              || Status.SUCCESS | profile.GEO_LOCATION.weight              | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Resource Version"          || Status.SUCCESS | profile.RESOURCE_VERSION.weight          | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "File Location"             || Status.SUCCESS | profile.FILE_LOCATION.weight             | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Title"            || Status.SUCCESS | profile.CITATION_TITLE.weight            | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Volume"           || Status.SUCCESS | profile.CITATION_VOLUME.weight           | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Issue"            || Status.SUCCESS | profile.CITATION_ISSUE.weight            | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Start Page"       || Status.SUCCESS | profile.CITATION_START_PAGE.weight       | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation End Page"         || Status.SUCCESS | profile.CITATION_END_PAGE.weight         | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Edition"          || Status.SUCCESS | profile.CITATION_EDITION.weight          | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Conference Place" || Status.SUCCESS | profile.CITATION_CONFERENCE_PLACE.weight | 0              | 0
        RECORD_ALL_VALID   | docAllValid     | "Citation Conference Date"  || Status.SUCCESS | profile.CITATION_CONFERENCE_DATE.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                                        | 2              | 6   // Success - Score 1 - 8 warnings. Expected 2 errors, 0 were returned. Failure of mandatory rules were evaluated as warnings instead.
        RECORD_ALL_INVALID | docAllInvalid   | "Contributor"               || Status.FAILURE | 0                                        | 3              | 4   // Success - 9 warnings. 2 unwanted for "datacite:nameIdentifier" and "datacite:affiliation" sub-element. Again 3 expected errors were evaluated as warnings instead.
        RECORD_ALL_INVALID | docAllInvalid   | "Funding Reference"         || Status.FAILURE | 0                                        | 1              | 3   // Success - Failure of mandatory rule evaluated as warning.
        RECORD_ALL_INVALID | docAllInvalid   | "Alternate Identifier"      || Status.FAILURE | 0                                        | 1              | 0   // Success - Failure of mandatory rule evaluated as warning.
        RECORD_ALL_INVALID | docAllInvalid   | "Related Identifier"        || Status.FAILURE | 0                                        | 2              | 1    //TODO
        RECORD_ALL_INVALID | docAllInvalid   | "Embargo Period Date"       || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Language"                  || Status.FAILURE | 0                                        | 1              | 0   // No error, as other language tags have valid values and cardinality rule succeeds. Should consider how to handle this.
        RECORD_ALL_INVALID | docAllInvalid   | "Publisher"                 || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Publication Date"          || Status.FAILURE | 0                                        | 1              | 0   // Success - 1 warning. Failure of mandatory rule evaluated as warning.
        RECORD_ALL_INVALID | docAllInvalid   | "Resource Type"             || Status.FAILURE | 0                                        | 2              | 0   // Success - Failure of 2 mandatory rules evaluated as warnings.
        RECORD_ALL_INVALID | docAllInvalid   | "Description"               || Status.SUCCESS | profile.DESCRIPTION.weight               | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Format"                    || Status.SUCCESS | 0                                        | 0              | 1   // Success - No warnings. Same case as language spec above.
        RECORD_ALL_INVALID | docAllInvalid   | "Resource Identifier"       || Status.FAILURE | 0                                        | 1              | 0   // Success - Failure of mandatory rule evaluated as warning.
        RECORD_ALL_INVALID | docAllInvalid   | "Access Rights"             || Status.FAILURE | 0                                        | 1              | 0
        RECORD_ALL_INVALID | docAllInvalid   | "Source"                    || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Subject"                   || Status.SUCCESS | profile.SUBJECT.weight                   | 0              | 3
        RECORD_ALL_INVALID | docAllInvalid   | "License Condition"         || Status.FAILURE | 0                                        | 2              | 0   // Success - Failure of 2 mandatory rules evaluated as warnings.
        RECORD_ALL_INVALID | docAllInvalid   | "Coverage"                  || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Size"                      || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Geo Location"              || Status.FAILURE | 0                                        | 2              | 7   // Success - 9 warnings. Expected 2 errors for missing mandatory sub-elements.
        RECORD_ALL_INVALID | docAllInvalid   | "Resource Version"          || Status.SUCCESS | profile.RESOURCE_VERSION.weight          | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "File Location"             || Status.SUCCESS | profile.FILE_LOCATION.weight             | 0              | 3
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Title"            || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Volume"           || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Issue"            || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Start Page"       || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation End Page"         || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Edition"          || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Conference Place" || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Citation Conference Date"  || Status.SUCCESS | 0                                        | 0              | 1
        RECORD_ALL_INVALID | docAllInvalid   | "Audience"                  || Status.SUCCESS | 0                                        | 0              | 1

        MEDIA_REP_2534     | docMediaRep2534 | "Title"                     || Status.SUCCESS | profile.TITLE.weight                     | 0              | 2
        MEDIA_REP_2534     | docMediaRep2534 | "Creator"                   || Status.SUCCESS | profile.CREATOR.weight                   | 0              | 7
        MEDIA_REP_2534     | docMediaRep2534 | "Contributor"               || Status.SUCCESS | 0                                        | 0              | 10
        MEDIA_REP_2534     | docMediaRep2534 | "Funding Reference"         || Status.SUCCESS | 0                                        | 0              | 8
        MEDIA_REP_2534     | docMediaRep2534 | "Alternate Identifier"      || Status.SUCCESS | profile.ALTERNATE_IDENTIFIER.weight      | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Related Identifier"        || Status.SUCCESS | profile.RELATED_IDENTIFIER.weight        | 0              | 4
        MEDIA_REP_2534     | docMediaRep2534 | "Embargo Period Date"       || Status.SUCCESS | 0                                        | 0              | 2
        MEDIA_REP_2534     | docMediaRep2534 | "Language"                  || Status.SUCCESS | profile.LANGUAGE.weight                  | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Publisher"                 || Status.SUCCESS | profile.PUBLISHER.weight                 | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Publication Date"          || Status.SUCCESS | profile.PUBLICATION_DATE.weight          | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Resource Type"             || Status.FAILURE | 0                                        | 1              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Description"               || Status.SUCCESS | profile.DESCRIPTION.weight               | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Format"                    || Status.SUCCESS | profile.FORMAT.weight                    | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Resource Identifier"       || Status.SUCCESS | profile.RESOURCE_IDENTIFIER.weight       | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Access Rights"             || Status.SUCCESS | profile.ACCESS_RIGHTS.weight             | 0              | 0
        MEDIA_REP_2534     | docMediaRep2534 | "Source"                    || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Subject"                   || Status.SUCCESS | profile.SUBJECT.weight                   | 0              | 3
        MEDIA_REP_2534     | docMediaRep2534 | "License Condition"         || Status.SUCCESS | 0                                        | 0              | 3
        MEDIA_REP_2534     | docMediaRep2534 | "Coverage"                  || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Size"                      || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Geo Location"              || Status.SUCCESS | 0                                        | 0              | 17
        MEDIA_REP_2534     | docMediaRep2534 | "Resource Version"          || Status.SUCCESS | 0                                        | 0              | 2
        MEDIA_REP_2534     | docMediaRep2534 | "File Location"             || Status.SUCCESS | 0                                        | 0              | 4
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Title"            || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Volume"           || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Issue"            || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Start Page"       || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation End Page"         || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Edition"          || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Conference Place" || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Citation Conference Date"  || Status.SUCCESS | 0                                        | 0              | 1
        MEDIA_REP_2534     | docMediaRep2534 | "Audience"                  || Status.SUCCESS | profile.AUDIENCE.weight                  | 0              | 0

    }

    //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()}"
    }

}
