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

if (rootProject.hasProperty('coverage') && Boolean.valueOf(rootProject.getProperty('coverage'))) {
    // we only apply the jacoco configuration if a system property is set, in order to avoid instrumentation if we
    // are not specifically asking for code coverage

    allprojects {
        if (!['performance', 'binary-compatibility'].contains(it.name)) {
            apply plugin: 'jacoco'
        }

        project.afterEvaluate {
            tasks.withType(JacocoReport) {
                if (name != 'jacocoAllReport' && name != 'jacocoAllIndyReport') {
                    sourceDirectories.from = sourceDirectories.from + files(project.sourceSets.main.allGroovy.srcDirs)
//                    classDirectories += files(project.sourceSets.main.output)
                }
            }
        }
    }

    // To avoid "Can't add different class with same name" fatal error
    // due to different classes generated when using Indy, create two reports
    // No need to include Java class directories since Groovy one includes those classes

    task jacocoMerge(type: JacocoMerge) {
        destinationFile = file("$buildDir/jacoco/jacoco-all.exec")

        allprojects {
            project.plugins.withType(JavaPlugin) {
                project.tasks.withType(Test) { task ->
                    if (sourceSets.test.allSource.srcDirs.any { it.exists() } && !task.name.contains('Indy')) {
                        executionData(task)
                    }
                }
            }
        }

        executionData = files(executionData).filter { f -> f.exists() }
    }

    task jacocoMergeIndy(type: JacocoMerge) {
        destinationFile = file("$buildDir/jacoco/jacoco-all-indy.exec")
        allprojects {
            project.plugins.withType(JavaPlugin) {
                project.tasks.withType(Test) { task ->
                    if (sourceSets.test.allSource.srcDirs.any { it.exists() } && task.name.contains('Indy')) {
                        executionData(task)
                    }
                }
            }
        }

        executionData = files(executionData).filter { f -> f.exists() }
    }

    task jacocoAllReport(type: JacocoReport, dependsOn: 'jacocoMerge') {
        executionData jacocoMerge.destinationFile
        reports {
            xml {
                enabled true
            }
            html {
                enabled true
            }
        }

        allprojects {
            project.plugins.withType(JavaPlugin) {
                def sd = sourceDirectories.from ?: files()
                def cd = classDirectories.from ?: files()
                sourceDirectories.from = sd + files(project.sourceSets.main.allGroovy.srcDirs, project.sourceSets.main.allJava.srcDirs)
                classDirectories.from = cd + files(compileGroovy.destinationDir)
            }
        }
    }

    task jacocoAllIndyReport(type: JacocoReport, dependsOn: 'jacocoMergeIndy') {
        executionData jacocoMergeIndy.destinationFile
        reports {
            xml {
                enabled true
            }
            html {
                enabled true
            }
        }

        allprojects {
            project.plugins.withType(JavaPlugin) {
                def sd = sourceDirectories.from ?: files()
                def cd = classDirectories.from ?: files()
                sourceDirectories.from = sd + files(project.sourceSets.main.allGroovy.srcDirs, project.sourceSets.main.allJava.srcDirs)
                classDirectories.from = cd + files(compileGroovyWithIndy.destinationDir)
            }
        }
    }

    check.dependsOn jacocoAllReport
    if (!rootProject.hasProperty('skipIndy')) {
        check.dependsOn jacocoAllIndyReport
    }

    tasks.sonarqube.dependsOn jacocoAllReport
    if (!rootProject.hasProperty('skipIndy')) {
        tasks.sonarqube.dependsOn jacocoAllIndyReport
    }
}
