buildscript {
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
}

plugins {
    id 'java'

    id 'jacoco-report-aggregation'

    alias(libs.plugins.gradle.versions)
    alias(libs.plugins.sonar)

    alias(libs.plugins.jreleaser)

    id 'com.dorongold.task-tree' version '4.0.1'
}

allprojects {
    group = group
    version = htmlSanityCheckVersion

    repositories {
        mavenCentral()
        mavenLocal()
    }

    tasks.register("info") {
        doLast
                {
                    println "project.name         : " + project.name
                    println "version              : " + version
                    println "project.version      : " + project.version
                    println "project.path         : " + project.path
                    println "projectDir           : " + projectDir
                    println "groupId              : " + project.group
                    println "targetCompatibility  : " + java.targetCompatibility
                    println "OS                   : " + System.properties["os.name"]
                    println "Java VM Name         : " + System.properties["java.vm.name"]
                    println "Java VM Vendor       : " + System.properties["java.vm.vendor"]
                    println "Java VM Version      : " + System.properties["java.vm.version"]
                    println "=" * 80
                }
    }
}

dependencies {
    // Add all subprojects to the aggregation
    subprojects.forEach {
        jacocoAggregation it
    }
}

reporting {
    reports {
        testCodeCoverageReport(JacocoCoverageReport)
    }
}

tasks.named('check') {
    dependsOn tasks.named('testCodeCoverageReport', JacocoReport)
}

ext.urls = [
        website            : "https://hsc.aim42.org/",
        issueTracker       : 'https://github.com/aim42/htmlSanityCheck/issues',

        scm                : 'https://github.com/aim42/htmlSanityCheck.git',
        connection         : 'scm:git:git://github.com/aim42/htmlSanityCheck.git',
        developerConnection: 'scm:git:ssh://github.com/aim42/htmlSanityCheck.git'
]

File baseBuildDir = file("${project.rootDir}/${Project.DEFAULT_BUILD_DIR_NAME}")
File mavenBuildRepo = new File(baseBuildDir, "maven-repo")

tasks.register("cleanMavenBuildRepo", Delete) {
    description "Clean intermediate local Maven Repository '${mavenBuildRepo}'"
    delete mavenBuildRepo
}

File mavenStagingRepo = new File(baseBuildDir, "staging-repo")

tasks.register("cleanMavenStagingRepo", Delete) {
    description "Clean intermediate staging Maven Repository '${mavenStagingRepo}'"
    delete mavenBuildRepo
}

tasks.register("copyOrgAim42ToStagingRepo", Copy) {
    description = "Copy 'org/aim42' from '${mavenBuildRepo}; to '${mavenStagingRepo}'"
    from new File(mavenBuildRepo, "org/aim42")
    into new File(mavenStagingRepo, "org/aim42")
}

copyOrgAim42ToStagingRepo.dependsOn(
        ':htmlSanityCheck-core:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository',
        ':htmlSanityCheck-gradle-plugin:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository',
        ':htmlSanityCheck-maven-plugin:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository'
)

jreleaserRelease.dependsOn(
        ':htmlSanityCheck-cli:build',
        copyOrgAim42ToStagingRepo,
)

jreleaser {
    project {
        license = 'Apache-2.0'
        links {
            homepage = urls.website
        }
        inceptionYear = '2014'
        copyright = '2024'

        authors = ['Gernot Starke', 'Gerd Aschemann']
    }

    release {
        github {
            repoOwner = 'aim42'
            overwrite = true

            tagName = '{{projectVersion}}'

            changelog {
                external = 'CHANGELOG.md'
            }

            prerelease {
                enabled = true
                pattern = '.*-rc\\d+$'
            }
        }
    }

    distributions {
        hsc {
            artifact {
                path = 'htmlSanityCheck-cli/build/distributions/{{distributionName}}-{{projectVersion}}.zip'
            }
            artifact {
                path = 'htmlSanityCheck-cli/build/distributions/{{distributionName}}-{{projectVersion}}.tar'
            }
            active = 'ALWAYS'
            distributionType = 'JAVA_BINARY'
            stereotype = 'CLI'
            sdkman {
                active = 'ALWAYS'
            }
        }
    }

    deploy {
        active = 'NEVER'

        maven {
            mavenCentral {
                app {
                    active = 'ALWAYS'
                    sign = false
                    url = 'https://central.sonatype.com/api/v1/publisher'
                    stagingRepository(mavenStagingRepo.toString())
                }
            }
        }
    }

    announce {
        active = 'ALWAYS'

        mastodon {
            active = 'ALWAYS'
            host = 'https://mastodon.social'

            statusTemplate = 'src/templates/jreleaser/mastodon.tpl'
        }
    }

    packagers {
        sdkman {
            active = 'ALWAYS'
            candidate = 'hsc'
            command = 'MAJOR'
        }
    }
}

configure(subprojects) {
    apply plugin: 'java'
    apply plugin: 'groovy'
    apply plugin: 'maven-publish'

    apply plugin: 'jacoco'
    apply plugin: 'signing'

    description "${rootProject.description} - Module ${project.name}"

    dependencies {
        implementation platform(libs.slf4j.bom)

        testImplementation platform(libs.spock)
        testImplementation "org.spockframework:spock-core"
        testImplementation "org.spockframework:spock-junit4"

        testImplementation libs.junit.vintage
    }

    java {
        toolchain {
            languageVersion = JavaLanguageVersion.of(8)
        }
        withSourcesJar()
    }

    publishing {
        publications.all { publication ->
            if (publication instanceof MavenPublication) {
                publication.pom {
                    name = project.name
                    description = project.description
                    url = urls.website
                    licenses {
                        license {
                            name = 'The Apache License, Version 2.0'
                            url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
                        }
                    }
                    developers {
                        developer {
                            id = 'gstarke'
                            name = 'Gernot Starke'
                            email = 'gs@gernotstarke.de'
                        }
                        developer {
                            id = 'ascheman'
                            name = 'Gerd Aschemann'
                            email = 'gerd@aschemann.net'
                        }
                        developer {
                            id = 'rdmueller'
                            name = 'Ralf D. Müller'
                            email = 'ralf.d.mueller@gmail.com'
                        }
                        developer {
                            id = 'ruhrotht'
                            name = 'Thomas Ruhroth'
                            email = 'Thomas.Ruhroth@msg.group'
                        }
                    }
                    scm {
                        connection = urls.connection
                        developerConnection = urls.developerConnection
                        url = urls.scm
                    }
                }
            }
        }
        repositories {
            maven {
                name = 'myLocalRepositoryForFullIntegrationTests'
                url = mavenBuildRepo
            }
            mavenLocal()
        }
    }

    tasks.withType(PublishToMavenRepository).named { it.contains("MyLocalRepositoryForFullIntegrationTests") }.configureEach {
        outputs.dir(mavenBuildRepo)
        outputs.upToDateWhen { false }
    }

    tasks.named('test', Test) {
        useJUnitPlatform()
    }

    check {
        finalizedBy jacocoTestReport // report is always generated after tests run
    }
    jacocoTestReport {
        reports {
            xml.required = true
        }
        dependsOn check // tests are required to run before generating the report
    }

    signing {
        required = { project.hasProperty('enableSigning') && project.property('enableSigning') == 'true' }
        if (project.hasProperty('useGpgCmd') && project.property('useGpgCmd') == 'true') {
            useGpgCmd()
        }
        sign publishing.publications
    }
}

def groovyVersion = GroovySystem.version
def groovyVersionMajorMinor = groovyVersion.split('\\.')[0..1].join('.')

tasks.named("dependencyUpdates").configure {
    gradleReleaseChannel = true

    resolutionStrategy {
        componentSelection { rules ->
            rules.all { ComponentSelection selection ->
                if (selection.candidate.version =~ /(alpha|M)/) {
                    selection.reject('Rejected alpha or milestone version')
                } else if (selection.candidate.group == 'org.spockframework') {
                    def spockGroovyVersion = selection.candidate.version.split('-')[2]
                    if (spockGroovyVersion != groovyVersionMajorMinor) {
                        selection.reject("Spock's Groovy version ($spockGroovyVersion) does not match project's Groovy major/minor version ($groovyVersionMajorMinor)")
                    }
                } else if (selection.candidate.group == 'org.codehaus.groovy') {
                    if (selection.candidate.version != groovyVersion) {
                        selection.reject("Groovy version is determined by Gradle API (${groovyVersion})")
                    }
                }
            }
        }
    }
}

sonar {
    properties {
        property "sonar.projectKey", System.getenv("SONAR_PROJECT_KEY") ?: "aim42_htmlSanityCheck"
        property "sonar.organization", System.getenv('SONAR_ORGANIZATION') ?: "aim42"
        property "sonar.host.url", System.getenv('SONAR_URL') ?: "https://sonarcloud.io"
        property "sonar.scm.provider", "git"
        property "sonar.coverage.jacoco.xmlReportPaths", "**/build/reports/jacoco/test/jacocoTestReport.xml"
        property "sonar.buildbreaker.skip", "false"
        property "sonar.qualitygate.wait", true
    }
}

tasks.register("publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository") {
    group("Publishing")
    description("Publishes all publications to the local Maven integration (test) repository")

    dependsOn(
            // For some reason it is necessary to add this task explicitly though it should be part of the
            // ":htmlSanityCheck-gradle-plugin:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository" task
            ":htmlSanityCheck-gradle-plugin:publishHtmlSanityCheckPluginMarkerMavenPublicationToMyLocalRepositoryForFullIntegrationTestsRepository",
            ":htmlSanityCheck-core:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository",
            ":htmlSanityCheck-gradle-plugin:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository",
            ":htmlSanityCheck-maven-plugin:publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository",
    )
}

final String INTEGRATION_TEST_DIRECTORY = "integration-test"

tasks.register("integrationTestOnly") {
    group("Verification")
    description("Perform all Integration Tests (Only)")

    dependsOn(
            ':publishAllPublicationsToMyLocalRepositoryForFullIntegrationTestsRepository',
            ':htmlSanityCheck-cli:installDist',
    )

    doLast {
        def result = exec {
            workingDir INTEGRATION_TEST_DIRECTORY
            commandLine((System.getProperty("os.name") ==~ /Windows.*/
                    ? "..\\gradlew.bat"
                    : "../gradlew"),
                    "integrationTest")
        }
        logger.debug "Script output: ${result}"
    }
}

tasks.register("cleanIntegrationTest", Delete) {
    group("Build")
    description("Perform clean for Integration Tests")

    doLast {
        def result = exec {
            workingDir INTEGRATION_TEST_DIRECTORY
            commandLine((System.getProperty("os.name") ==~ /Windows.*/
                    ? "..\\gradlew.bat"
                    : "../gradlew"),
                    "clean")
        }
        logger.debug "Script output: ${result}"
    }
}
clean.dependsOn(cleanIntegrationTest)

tasks.register("integrationTest") {
    group("Verification")
    description("Run overall integration tests (and publish/install first)")
    dependsOn(
            'integrationTestOnly',
    )
}

/*
 * Copyright Gernot Starke and aim42 contributors.
 *
 * Licensed 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
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 */
