import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent

buildscript {
    repositories {
        mavenCentral()
    }
}

plugins {
    id "org.sonarqube" version "5.0.0.4638"
    //id "com.github.nbaztec.coveralls-jacoco" version "1.2.15"
    //id 'com.github.kt3k.coveralls' version '2.12.0'
}

repositories { 
    // https://stackoverflow.com/questions/36029754/force-gradle-to-use-http-instead-of-https
    // https://discuss.gradle.org/t/how-to-change-gradle-plugin-portal-from-https-to-http/10847/12
    mavenLocal()
    mavenCentral()
}

ext.junit4Version        = '4.13.2'
ext.junitVintageVersion  = '4.12.1'
ext.junitPlatformVersion = '1.5.2'
ext.junitJupiterVersion  = '5.10.2'
ext.log4jVersion         = '2.23.1'

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'

// https://stackoverflow.com/questions/46233314/gradle-android-jacoco-and-junit5
apply plugin: 'jacoco'
jacoco {
    toolVersion = '0.8.12'
}
jacocoTestCoverageVerification {
    violationRules {
        rule {
            limit {
                minimum = 0.5
            }
        }
    }
}

sourceCompatibility = JavaVersion.VERSION_19
targetCompatibility = JavaVersion.VERSION_19

compileJava {
    options.compilerArgs += ["--enable-preview"]
}

compileTestJava {
    options.compilerArgs += ['-parameters', '-g', '--enable-preview']
}

//Buildship doesn't use that hook (https://discuss.gradle.org/t/when-does-buildship-eclipse-customization-run/20781/2)
//you need to run `gradle eclipse` separately
eclipse.jdt.file.withProperties { props ->
    props['org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures']= 'enabled'
    props['org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures']= 'ignore'
}

// gradle support from JUnit5 team that we removed after gradle native support for JUnit5: http://junit.org/junit5/docs/current/user-guide/#running-tests-build-gradle
test {
    jvmArgs '--enable-preview'
    
    // https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html
    // Enable JUnit 5 (Gradle 4.6+).
    useJUnitPlatform {
            includeEngines 'junit-jupiter', 'junit-vintage'
            // excludeEngines 'custom-engine'

            // includeTags 'fast'
            // excludeTags 'slow'
    }

    // Always run tests, even when nothing changed.
    dependsOn 'cleanTest'
}

dependencies {
    testImplementation "org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}"
	//testCompileOnly "org.junit.jupiter:junit-jupiter-params:${junitJupiterVersion}"
    testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}"
    testCompileOnly "junit:junit:${junit4Version}"
    testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junitJupiterVersion}"

    // Enable use of the JUnitPlatform Runner within the IDE
	//testCompile("org.junit.platform:junit-platform-runner:${junitPlatformVersion}")
    // Only needed to run tests in an (IntelliJ) IDE(A) that bundles an older version
	//testRuntimeOnly("org.junit.platform:junit-platform-launcher:${junitPlatformVersion}")
    
	// To avoid compiler warnings about @API annotations in JUnit code
	testCompileOnly('org.apiguardian:apiguardian-api:1.1.2')
    implementation('org.apiguardian:apiguardian-api:1.1.2')

    // To use Log4J's LogManager
	testRuntimeOnly("org.apache.logging.log4j:log4j-core:${log4jVersion}")
	testRuntimeOnly("org.apache.logging.log4j:log4j-jul:${log4jVersion}")

    implementation("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
    implementation "junit:junit:${junit4Version}"
}

mainClassName = ' '

/*
Default:
src/main/java
src/main/resources
src/test/java
src/test/resources
*/
sourceSets {
   main {
      java {
         srcDirs = ['src']
      }
   }
   test {
       java {
           srcDirs = ['src']
      }
   }
}

// https://github.com/junit-team/junit5/issues/1024#issuecomment-354384992
afterEvaluate {
    def junitPlatformTestTask = project.tasks.getByName('test')

    project.task(type: JacocoReport, "jacocoJupTestReport") {
        executionData(junitPlatformTestTask)
        sourceSets(sourceSets.main)
        sourceDirectories.from = files(sourceSets.main.allSource.srcDirs)
        classDirectories.from = files("${buildDir}/classes/java/test")
        //files(sourceSets.main.output)

        reports {
            xml.required = true
            xml.destination file("${buildDir}/reports/jacoco/report.xml")
            html.required = true
            html.destination file("${buildDir}/reports/jacoco/html")
        }
    }

    check.dependsOn jacocoJupTestReport

    // coverallsJacoco {
    //     def jacocoJupTestReportTask = project.tasks.getByName('jacocoJupTestReport')
    //     reportPath = "${buildDir}/reports/jacoco/report.xml"
    //     reportSourceSets = files(jacocoJupTestReportTask.sourceDirectories.collect{ it.listFiles() }.flatten())
    // } 
}

// https://github.com/ben-manes/caffeine/blob/master/build.gradle
// coveralls {
//     jacocoReportPath = "${buildDir}/reports/jacoco/report.xml"
// }  

// https://github.com/codeclimate/test-reporter/issues/243
// task jacocoFixForCodeClimate(type: Copy) {
//     from 'build/reports/jacoco/report.xml'
//     into '../'
//     rename { String fileName ->
//         fileName.replace("report.xml", "jacoco.xml")
//     }
//     filter { line -> line.replaceAll("com/", "webapp/src/main/java/com/") }
// }

// https://stackoverflow.com/questions/3963708/gradle-how-to-display-test-results-in-the-console-in-real-time
tasks.withType(Test) {
    testLogging {        
        // set options for log level LIFECYCLE
        events TestLogEvent.FAILED,
               //TestLogEvent.PASSED,
               TestLogEvent.SKIPPED,
               TestLogEvent.STANDARD_ERROR
               //TestLogEvent.STANDARD_OUT
        exceptionFormat TestExceptionFormat.FULL
        showCauses true
        showExceptions true
        showStackTraces true
        // uncomment line below for print outouts to show
        //showStandardStreams true

        // set options for log level DEBUG and INFO
        debug {
            events TestLogEvent.STARTED,
                   TestLogEvent.FAILED,
                   TestLogEvent.PASSED,
                   TestLogEvent.SKIPPED,
                   TestLogEvent.STANDARD_ERROR,
                   TestLogEvent.STANDARD_OUT
            exceptionFormat TestExceptionFormat.FULL
        }
        info.events = debug.events
        info.exceptionFormat = debug.exceptionFormat
        
        afterSuite { desc, result ->
        if (!desc.parent) { // will match the outermost suite            
                def output = "Results: ${result.resultType} (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)"
                def startItem = '|  ', endItem = '  |'
                def repeatLength = startItem.length() + output.length() + endItem.length()
                println('\n' + ('-' * repeatLength) + '\n' + startItem + output + endItem + '\n' + ('-' * repeatLength))
            }
        }
    }
}