import java.util.regex.Pattern

/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

configurations {
    tests
    javadocs
}

sourceSets {
    main {
        if (jdkVersion > 8) {
            output.dir(JAVA9_OUT, builtBy: 'cacheJava9')
        }
    }
    test {
        if (jdkVersion > 8) {
            output.dir(TEST9_OUT, builtBy: 'cacheTest9')
        }
    }
}

dependencies {
    api project(':poi')
    api project(path:':poi', configuration: 'archives')
    api "org.apache.logging.log4j:log4j-api:${log4jVersion}"
    api "org.apache.commons:commons-math3:${commonsMathVersion}"
    api "commons-codec:commons-codec:${commonsCodecVersion}"

    testImplementation project(path: ':poi', configuration: 'tests')
    testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
    testRuntimeOnly "org.apiguardian:apiguardian-api:${apiGuardianVersion}"

    if (SAXON_TEST) {
        testRuntimeOnly "net.sf.saxon:Saxon-HE:${saxonVersion}"
    }

    javadocs project(':poi')
    javadocs project(':poi-ooxml')
}

final MODULE_NAME = 'org.apache.poi.scratchpad'
final Pattern MODULE_NOT_REGEX = ~'(poi[/\\\\][^/\\\\]+$|batik-script)'
final Pattern MODULE_REGEX = ~'\\.jar$'
final List MAIN_MODULE_PATH = sourceSets.main.runtimeClasspath.findAll{ it.path =~ MODULE_REGEX }.collect{ it.parent }.unique()
final List TEST_MODULE_PATH = sourceSets.test.runtimeClasspath.findAll{ it.path =~ MODULE_REGEX && !(it.path =~ MODULE_NOT_REGEX) }.collect{ it.parent }.unique()

task compileJava9(type: JavaCompile) {
    dependsOn 'compileJava', ':poi:jar'

    javaCompiler = javaToolchains.compilerFor {
        languageVersion = JavaLanguageVersion.of(jdkVersion)
        if (jdkVendor != '') vendor = JvmVendorSpec.matching(jdkVendor)
    }
    destinationDirectory = file(JAVA9_OUT + VERSIONS9)
    source = file(JAVA9_SRC)
    classpath = files()
    options.compilerArgs = [
        '--patch-module', "${MODULE_NAME}=${sourceSets.main.output.classesDirs.asPath}",
        '--module-path', files(MAIN_MODULE_PATH).asPath
    ]

    onlyIf {
        jdkVersion > 8
    }
}

task cacheJava9(type: Copy) {
    dependsOn 'compileJava9'

    from(file(JAVA9_OUT + VERSIONS9))
    into(JAVA9_SRC)
}

task compileTest9(type: JavaCompile) {
    dependsOn 'compileTestJava', ':poi:jar'

    javaCompiler = javaToolchains.compilerFor {
        languageVersion = JavaLanguageVersion.of(jdkVersion)
        if (jdkVendor != '') vendor = JvmVendorSpec.matching(jdkVendor)
    }
    destinationDirectory = file(TEST9_OUT + VERSIONS9)
    source = file(TEST9_SRC)
    options.compilerArgs = [
        '--patch-module', "${MODULE_NAME}=${(sourceSets.main.output.classesDirs + sourceSets.test.output.classesDirs).asPath}",
        '--module-path', files(TEST_MODULE_PATH).asPath
    ]
    classpath = files()

    onlyIf {
        jdkVersion > 8
    }
}


task cacheTest9(type: Copy) {
    dependsOn 'compileTest9'

    from(file(TEST9_OUT + VERSIONS9))
    into(TEST9_SRC)
}

jar {
    destinationDirectory = file("../build/dist/maven/${project.archivesBaseName}")

    if (jdkVersion == 8) {
        into('META-INF/versions/9') {
            from JAVA9_SRC include '*.class'
        }
    }

    manifest {
        attributes('Automatic-Module-Name': MODULE_NAME, 'Multi-Release': 'true')
    }
}

// Create a separate jar for test-code to depend on it in other projects
// See http://stackoverflow.com/questions/5144325/gradle-test-dependency
task testJar(type: Jar, dependsOn: testClasses) {
    destinationDirectory = file("../build/dist/maven/${project.archivesBaseName}-tests")

    classifier 'tests'
    // ignore second module-info.class from main
    duplicatesStrategy = 'exclude'

    if (jdkVersion == 8) {
        into('META-INF/versions/9') {
            from TEST9_SRC include '*.class'
        }
    }

    from sourceSets.test.output + sourceSets.main.output

    manifest {
        attributes('Automatic-Module-Name': MODULE_NAME, 'Multi-Release': 'true')
    }
}

javadoc {
    doFirst {
        options {
            classpath += configurations.javadocs.files
        }
    }
}

// without this dependency, parallel building sometimes fails because the javadoc
// task tries to access a jar-file which is not yet fully built
javadoc.mustRunAfter ':poi-ooxml:jar'

javadocJar {
    metaInf {
        from("$projectDir/../legal/LICENSE")
        from("$projectDir/../legal/NOTICE")
    }
}

sourcesJar {
    metaInf {
        from("$projectDir/../legal/LICENSE")
        from("$projectDir/../legal/NOTICE")
    }
}

artifacts {
    tests testJar
}

test {
    dependsOn { testJar }

    systemProperties['junit.jupiter.execution.parallel.enabled'] = 'true'

    doFirst {
        if (jdkVersion > 8) {
            jvmArgs += [
                '--add-modules', MODULE_NAME,
                '--module-path', '../build/dist/maven/poi-scratchpad-tests' + File.pathSeparator + files(TEST_MODULE_PATH).asPath,
            ]
        }
    }
}

publishing {
    publications {
        POI(MavenPublication) {
            pom {
                name = 'Apache POI'
                description = 'Apache POI - Java API To Access Microsoft Format Files (Scratchpad)'
            }
        }
    }
}
