apply plugin: 'jacoco'

jacoco {
    toolVersion(versions.jacoco)
}

def mergedJacocoExec = file("${project.buildDir}/jacoco/jacocoMerged.exec")

def merge = tasks.register('jacocoMergeReports', JacocoMerge) {
    group = "Reporting"
    description = "Merge all jacoco reports from projects into one."

    ListProperty<File> jacocoFiles = project.objects.listProperty(File.class)
    project.subprojects { subproject ->
        subproject.plugins.withId("jacoco") {
            project.logger.info("${subproject.name} has Jacoco plugin applied")
            subproject.tasks.withType(Test) { task ->
                File destFile = task.extensions.getByType(JacocoTaskExtension.class).destinationFile
                if (destFile.exists() && !task.name.contains("Release")) {
                    jacocoFiles.add(destFile)
                }
            }
        }
    }

    executionData(jacocoFiles)
    destinationFile(mergedJacocoExec)
}

tasks.register('jacocoFullReport', JacocoReport) {
    dependsOn merge
    group = "Reporting"
    description = "Generate full Jacoco coverage report including all modules."

    getClassDirectories().setFrom(files())
    getSourceDirectories().setFrom(files())
    getExecutionData().setFrom(files())

    reports {
        xml.enabled = true
        html.enabled = true
        csv.enabled = false
    }

    // Always run merging, as all input calculation is done in doFirst {}
    outputs.upToDateWhen { false }
    // Task will run anyway even if initial inputs are empty
    onlyIf = { true }

    project.subprojects { subproject ->
        subproject.plugins.withId("jacoco") {
            project.logger.info("${subproject.name} has Jacoco plugin applied")
            subproject.plugins.withId("kotlin-android") {
                project.logger.info("${subproject.name} is android project")
                def mainSources = subproject.extensions.findByName("android").sourceSets['main']
                project.logger.info("Android sources: ${mainSources.java.srcDirs}")
                mainSources.java.srcDirs.forEach {
                    additionalSourceDirs(it)
                }
                project.logger.info("Subproject exclude: ${subproject.jacocoExclude}")
                additionalClassDirs(fileTree(
                        dir: "${subproject.buildDir}/tmp/kotlin-classes/debug",
                        excludes: subproject.jacocoExclude
                ))
            }
            subproject.plugins.withId("kotlin") { plugin ->
                project.logger.info("${subproject.name} is common kotlin project")
                SourceDirectorySet mainSources = subproject.extensions.getByName("kotlin")
                        .sourceSets[SourceSet.MAIN_SOURCE_SET_NAME]
                        .kotlin
                mainSources.srcDirs.forEach {
                    project.logger.debug("Adding sources: $it")
                    additionalSourceDirs(it)
                }
                project.logger.info("Subproject exclude: ${subproject.jacocoExclude}")
                additionalClassDirs(fileTree(
                        dir: "${subproject.buildDir}/classes/kotlin/main",
                        excludes: subproject.jacocoExclude
                ))
            }

            subproject.tasks.withType(Test) { task ->
                File destFile = task.extensions.getByType(JacocoTaskExtension.class).destinationFile
                if (destFile.exists() && !task.name.contains("Release")) {
                    project.logger.info("Adding execution data: $destFile")
                    executionData(destFile)
                }
            }
        }
    }

}
