/*
 *  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.addSigFile = { File sigFile, c, ext, n ->
            if (sigFile.exists()) {
                project.artifacts.add('archives', sigFile) {
                    if (n) {
                        name = n
                    }
                    classifier = c
                    type = 'asc'
                    extension = ext
                }
            }
        }
        ext.signWithClassifier = { String c, File f ->
            if (rootProject.isReleaseVersion) {
                signing.sign(c, f)
                def ascFile = new File(f.parent, f.name + '.asc')
                addSigFile(ascFile, c, 'jar.asc', null)
            }
        }
        ext.signWithName = { String baseName, File f ->
            if (rootProject.isReleaseVersion) {
                signing.sign(null, f)
                def ascFile = new File(f.parent, f.name + '.asc')
                addSigFile(ascFile, null, 'jar.asc', baseName)
            }
        }
        ext.signArchiveTask = { archiveTask ->
            if (rootProject.isReleaseVersion) {
                signing.sign(archiveTask.classifier, archiveTask.archivePath)
                def ascFile = new File(archiveTask.destinationDir, archiveTask.archiveName + '.asc')
                addSigFile(ascFile, archiveTask.classifier, archiveTask.extension + '.asc', archiveTask.baseName)
            }
        }

        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 jarjar.outputFile
            archives sourceJar
            archives javadocJar
            archives groovydocJar
        }

        configurations.archives.with {
            artifacts.removeAll(artifacts.find { it.name =~ 'raw' } )
        }

        [uploadArchives, install]*.with {
            dependsOn([grooidjar, jarjar, sourceJar, javadocJar, groovydocJar])
            if (rootProject.indyCapable()) {
                dependsOn jarjarWithIndy
            }
            doFirst {
                if (rootProject.indyCapable()) {
                    project.artifacts.add('archives', jarjarWithIndy.outputFile)
                }
                def grooidJarFile = rootProject.ext.deriveFile(jarjar.outputFile, 'grooid')
                if (grooidJarFile.exists()) {
                    project.artifacts.add('archives', grooidJarFile)
                }
            }
        }

        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
                signWithName(jar.baseName, jarjar.outputFile)
                signArchiveTask(sourceJar)
                signArchiveTask(javadocJar)
                signArchiveTask(groovydocJar)
                def indyJar = rootProject.ext.deriveFile(jarjar.outputFile, 'indy')
                if (indyJar.exists()) {
                    signWithClassifier('indy', indyJar)
                }
                def grooidJarFile = rootProject.ext.deriveFile(jarjar.outputFile, 'grooid')
                if (grooidJarFile.exists()) {
                    signWithClassifier('grooid', grooidJarFile)
                }
            }
        }
    }
}

// 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 {
        if (!rootProject.indyCapable()) {
            throw new GradleException("Indy must be enabled to upload archives")
        }

        project.artifacts.add('archives', distBin) { name = 'groovy-binary' }
        project.artifacts.add('archives', sourceAllJar) { name = 'groovy-all' }
        project.artifacts.add('archives', javadocAllJar) { name = 'groovy-all' }
        project.artifacts.add('archives', groovydocAllJar) { name = 'groovy-all' }
        signArchiveTask(sourceAllJar)
        signArchiveTask(javadocAllJar)
        signArchiveTask(groovydocAllJar)

        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 optionalModules = [
        'groovy-bsf',
        'groovy-cli-commons',
        'groovy-dateutil',
        'groovy-jaxb',
        'groovy-yaml'
]

ext.pomAll = {
    addFilter('groovy') { artifact, file ->
        !(artifact.name.contains('groovy-all')) &&
                !(artifact.name.contains('groovy-binary')) &&
                !(artifact.name.contains('backport'))
    }
    addFilter('all') { artifact, file ->
        // add an arbitrary artifact, so that the pom file is generated
        // we adjust the packaging attribute later
        artifact.name.contains('groovy-binary')
    }
    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 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()
        }
    }

    groovypom.whenConfigured(removeJarjaredDependencies)

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

    // pom for "all" dependencies
    def allpom = pom('all', pomConfigureClosureWithoutTweaks)
    allpom.artifactId = 'groovy-all'
    allpom.whenConfigured { p ->
        // this is the only way to get a handle on `maven.Dependency`
        def dependencyClass = p.dependencies[0].getClass()
        p.dependencies.clear()
        // defer setting packaging until here otherwise gets overwritten
        p.packaging = 'pom'
        allprojects {
            if (it.name.startsWith('groovy') && !optionalModules.contains(it.name)) {
                def dep = dependencyClass.newInstance()
                dep.groupId = 'org.codehaus.groovy'
                dep.artifactId = it.name
                dep.version = version
                p.dependencies.add(dep)
            }
        }
    }

    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
    }
}
