/*
 *  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.
 */

boolean isUsingArtifactory = rootProject.hasProperty('artifactoryUser') && rootProject.artifactoryUser &&
        rootProject.hasProperty('artifactoryPassword') && rootProject.artifactoryPassword

if (isUsingArtifactory) {
    logger.lifecycle 'Deployment environment set to Artifactory'
}

def embedded = ['asm', 'asm-util', 'asm-analysis', 'asm-tree', 'asm-commons', 'antlr', 'commons-cli', 'openbeans']
def removeJarjaredDependencies = { p ->
    p.dependencies.removeAll(p.dependencies.findAll {
        it.groupId == 'org.codehaus.groovy' || embedded.contains(it.artifactId)
    })
}

allprojects {
    if (project == rootProject || modules().contains(project)) {
        apply plugin: 'maven'
        apply from: "${rootProject.projectDir}/gradle/pomconfigurer.gradle"
        install.dependsOn checkCompatibility
    }
}

apply from: 'gradle/backports.gradle'

ext.basename = { String s -> s.take(s.lastIndexOf('.')) }
ext.deriveFile = { File archive, String suffix -> new File(archive.parent, basename(archive.name) + "-${suffix}.jar") }

allprojects {
    if (project == rootProject || modules().contains(project)) {
        ext.signWithClassifier = { String c, File f ->
            if (rootProject.isReleaseVersion) {
                signing.sign(c, f)
                def ascFile = new File(f.parent, f.name + '.asc')
                if (ascFile.exists()) {
                    project.artifacts.add('archives', ascFile) {
                        classifier = c
                        type = 'asc'
                        extension = 'jar.asc'
                    }
                }
            }
        }

        ext.signArchiveTask = { archiveTask ->
            if (rootProject.isReleaseVersion) {
                signing.sign(archiveTask.classifier, archiveTask.archivePath)
                def ascFile = new File(archiveTask.destinationDir, archiveTask.archiveName + '.asc')
                if (ascFile.exists()) {
                    project.artifacts.add('archives', ascFile) {
                        name = archiveTask.baseName
                        classifier = archiveTask.classifier
                        type = 'asc'
                        extension = archiveTask.extension + '.asc'
                    }
                }
            }
        }

        uploadArchives {
            repositories {
                mavenDeployer {
                    pom pomConfigureClosure
                    beforeDeployment { MavenDeployment deployment -> if (rootProject.isReleaseVersion) signing.signPom(deployment) }
                }
            }
        }

        install {
            repositories {
                mavenInstaller {
                    pom pomConfigureClosure
                    beforeDeployment { MavenDeployment deployment -> if (rootProject.isReleaseVersion) signing.signPom(deployment) }
                }
            }
        }

        artifacts {
            archives jar
            archives sourceJar
            archives javadocJar
            archives groovydocJar
        }

        [uploadArchives, install]*.with {
            // dependency on jarAllAll should in theory be replaced with jar, jarWithIndy but
            // in practice, it is faster
            dependsOn([jarAllAll, sourceJar, javadocJar, groovydocJar])
            doFirst {
                if (rootProject.useIndy()) {
                    new GradleException('You cannot use uploadArchives or install task with the flag [indy] turned'
                            + ' on because the build handles indy artifacts by itself in that case.')
                }
                def indyJar = rootProject.ext.deriveFile(jar.archivePath, 'indy')
                if (indyJar.exists()) {
                    project.artifacts.add('archives', indyJar)
                }
                def grooidJar = rootProject.ext.deriveFile(jar.archivePath, 'grooid')
                if (grooidJar.exists()) {
                    project.artifacts.add('archives', grooidJar)
                }
            }
        }

        install {
            doFirst {
                // gradle doesn't expect us to mutate configurations like we do here
                // so signing the configuration won't work and we do it manually here
                signArchiveTask(jar)
                signArchiveTask(sourceJar)
                signArchiveTask(javadocJar)
                signArchiveTask(groovydocJar)
                def indyJar = rootProject.ext.deriveFile(jar.archivePath, 'indy')
                if (indyJar.exists()) {
                    signWithClassifier('indy', indyJar)
                }
                def grooidJar = rootProject.ext.deriveFile(jar.archivePath, 'grooid')
                if (grooidJar.exists()) {
                    signWithClassifier('grooid', grooidJar)
                }
            }
        }
    }
}

// the root project generates several alternate artifacts, e.g. 'groovy-all'
// we don't want them in the root project so add them as artifacts with a modified name
// we'll exclude the original artifacts during publication with an exclude pattern
[uploadArchives, install]*.with {
    dependsOn([sourceAllJar, javadocAllJar, groovydocAllJar, distBin, distDoc, dist, distBin])
    doFirst {
        project.artifacts.add('archives', jarAll) {
            name = 'groovy-all'
        }
        project.artifacts.add('archives', sourceAllJar) {
            name = 'groovy-all'
        }
        project.artifacts.add('archives', javadocAllJar) {
            name = 'groovy-all'
        }
        project.artifacts.add('archives', groovydocAllJar) {
            name = 'groovy-all'
        }
        project.artifacts.add('archives', distBin) {
            name = 'groovy-binary'
        }
        signArchiveTask(jarAll)
        signArchiveTask(sourceAllJar)
        signArchiveTask(javadocAllJar)
        signArchiveTask(groovydocAllJar)

        // TODO rework these?
        if (isReleaseVersion) {
            signing.sign(distBin.archivePath)
            def ascFile = new File(distBin.destinationDir, distBin.archiveName + '.asc')
            if (ascFile.exists()) {
                project.artifacts.add('archives', ascFile) {
                    name = 'groovy-binary'
                    type = 'asc'
                    extension = 'zip.asc'
                }
            }
            signing.sign(distSrc.archivePath)
            signing.sign(distDoc.archivePath)
            signing.sign(dist.archivePath)
        }

        tasks.withType(Jar).matching { it.name.startsWith('backport') }.each { t ->
            project.artifacts.add('archives', t.archivePath) {
                name = t.baseName
                type = 'jar'
                classifier = t.classifier
            }
            if (isReleaseVersion) {
                signing.sign(t.classifier, t.archivePath)
                def ascFile = new File(t.destinationDir, t.archiveName + '.asc')
                if (ascFile.exists()) {
                    project.artifacts.add('archives', ascFile) {
                        name = t.baseName
                        classifier = t.classifier
                        type = 'asc'
                        extension = t.extension + '.asc'
                    }
                }
            }
        }

        def indyJar = deriveFile(jarAll.archivePath, 'indy')
        if (indyJar.exists()) {
            project.artifacts.add('archives', indyJar)
            signWithClassifier('indy', indyJar)
        }
        def grooidJar = deriveFile(jarAll.archivePath, 'grooid')
        if (grooidJar.exists()) {
            project.artifacts.add('archives', grooidJar)
            signWithClassifier('grooid', grooidJar)
        }
    }
}

ext.pomAll = {
    addFilter('groovy') { artifact, file ->
        !(artifact.name.contains('groovy-all')) &&
                !(artifact.name.contains('groovy-binary')) &&
                !(artifact.name.contains('backport'))
    }
    addFilter('all') { artifact, file ->
        artifact.name.contains('groovy-all')
    }
    addFilter('binary') { artifact, file ->
        artifact.name.contains('groovy-binary')
    }
    project.backports.each { pkg, classes ->
        addFilter("backports-$pkg") { artifact, file ->
            artifact.name == "groovy-backports-$pkg"
        }
    }

    // regular pom
    def groovypom = pom('groovy', pomConfigureClosure)

    // pom for 'all'
    def allpom = pom('all', pomConfigureClosure)
    allpom.artifactId = 'groovy-all'

    // pom for binary zip
    def binarypom = pom('binary', pomConfigureClosureWithoutTweaks)
    binarypom.artifactId = 'groovy-binary'

    // poms for backports
    project.backports.each { pkg, classes ->
        String id = "backports-$pkg"
        def backportPom = pom(id, pomConfigureClosureWithoutTweaks)
        backportPom.artifactId = "groovy-$id"
        backportPom.whenConfigured { p ->
            p.dependencies.clear()
        }
    }

    modules().each { sp ->
        sp.install.repositories.mavenInstaller.pom.whenConfigured { subpom ->
            // add dependencies of other modules
            allpom.dependencies.addAll(subpom.dependencies)
        }
        sp.uploadArchives.repositories.mavenDeployer.pom.whenConfigured { subpom ->
            // add dependencies of other modules
            allpom.dependencies.addAll(subpom.dependencies)
        }
    }


    groovypom.whenConfigured(removeJarjaredDependencies)
    allpom.whenConfigured(removeJarjaredDependencies)

    binarypom.whenConfigured { p ->
        p.dependencies.clear()
    }

    beforeDeployment { MavenDeployment deployment -> if (isReleaseVersion) signing.signPom(deployment) }
}

install {
    // make sure dependencies poms are built *before* the all pom
    dependsOn(modules()*.install)
    repositories {
        mavenInstaller pomAll
    }
}

uploadArchives {
    // make sure dependencies poms are built *before* the all pom
    dependsOn(modules()*.uploadArchives)
    repositories {
        mavenDeployer pomAll
    }
}
