// Top-level build file where you can add configuration options common to all sub-projects/modules.

import io.gitlab.arturbosch.detekt.Detekt
import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

buildscript {
    // This logic is duplicated in the allprojects block: I don't know how to fix that.
    repositories {
        maven {
            name "Mozilla Nightly"
            url "https://nightly.maven.mozilla.org/maven2"
            content {
                // Improve performance: only check moz maven for mozilla deps.
                includeGroupByRegex RepoMatching.mozilla
            }
        }

        maven {
            name "Mozilla"
            url "https://maven.mozilla.org/maven2"
            content {
                // Improve performance: only check moz maven for mozilla deps.
                includeGroupByRegex RepoMatching.mozilla
            }
        }

        if (ExtraRepositories.mozillaStaging) {
            maven {
                name "Mozilla Staging"
                url "https://maven-default.stage.mozaws.net/maven2"
                content {
                    // Improve performance: only check moz maven for mozilla deps.
                    includeGroupByRegex RepoMatching.mozilla
                }
            }
        }

        if (project.hasProperty("googleRepo")) {
            maven {
                name "Google"
                allowInsecureProtocol true // Local Nexus in CI uses HTTP
                url project.property("googleRepo")
            }
        } else {
            google() {
                content {
                    // Improve performance: only check google maven for google deps.
                    includeGroupByRegex RepoMatching.androidx
                    includeGroupByRegex RepoMatching.comAndroid
                    includeGroupByRegex RepoMatching.comGoogle
                }
            }
        }

        if (project.hasProperty("centralRepo")) {
            maven {
                name "MavenCentral"
                url project.property("centralRepo")
                allowInsecureProtocol true // Local Nexus in CI uses HTTP
            }
        } else {
            mavenCentral() {
                content {
                    // Improve security: don't search deps with known repos.
                    excludeGroupByRegex RepoMatching.mozilla
                    excludeGroupByRegex RepoMatching.androidx
                    excludeGroupByRegex RepoMatching.comAndroid
                }
            }
        }
    }

    dependencies {
        classpath ComponentsDependencies.tools_androidgradle
        classpath ComponentsDependencies.tools_kotlingradle
        classpath FenixDependencies.tools_benchmarkgradle
        classpath ComponentsDependencies.androidx_safeargs
        classpath FenixDependencies.osslicenses_plugin
        classpath "org.mozilla.telemetry:glean-gradle-plugin:${Versions.mozilla_glean}"
        classpath "${ApplicationServicesConfig.groupId}:tooling-nimbus-gradle:${ApplicationServicesConfig.version}"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }

    // Variables in plugins {} aren't directly supported. Hack around it by setting an
    // intermediate variable which can pull from FenixDependenciesPlugin.kt and be used later.
    ext {
        detekt_plugin = Versions.detekt
        ksp_plugin = Versions.ksp_plugin
        protobuf_plugin = FenixVersions.protobuf_plugin
        python_envs_plugin = Versions.python_envs_plugin
    }
}

plugins {
    id("io.gitlab.arturbosch.detekt").version("$detekt_plugin")
    id("com.google.devtools.ksp").version("$ksp_plugin")
}

allprojects {
    // This logic is duplicated in the buildscript block: I don't know how to fix that.
    repositories {
        maven {
            name "Mozilla Nightly"
            url "https://nightly.maven.mozilla.org/maven2"
            content {
                // Improve performance: only check moz maven for mozilla deps.
                includeGroupByRegex RepoMatching.mozilla
            }
        }

        maven {
            name "Mozilla"
            url "https://maven.mozilla.org/maven2"
            content {
                // Improve performance: only check moz maven for mozilla deps.
                includeGroupByRegex RepoMatching.mozilla
            }
        }

        if (ExtraRepositories.mozillaStaging) {
            maven {
                name "Mozilla Staging"
                url "https://maven-default.stage.mozaws.net/maven2"
                content {
                    // Improve performance: only check moz maven for mozilla deps.
                    includeGroupByRegex RepoMatching.mozilla
                }
            }
        }

        if (project.hasProperty("googleRepo")) {
            maven {
                name "Google"
                url project.property("googleRepo")
                allowInsecureProtocol true // Local Nexus in CI uses HTTP
            }
        } else {
            google() {
                content {
                    // Improve performance: only check google maven for google deps.
                    includeGroupByRegex RepoMatching.androidx
                    includeGroupByRegex RepoMatching.comAndroid
                    includeGroupByRegex RepoMatching.comGoogle
                }
            }
        }

        if (project.hasProperty("centralRepo")) {
            maven {
                name "MavenCentral"
                url project.property("centralRepo")
                allowInsecureProtocol true // Local Nexus in CI uses HTTP
            }
        } else {
            mavenCentral() {
                content {
                    // Improve security: don't search deps with known repos.
                    excludeGroupByRegex RepoMatching.mozilla
                    excludeGroupByRegex RepoMatching.androidx
                    excludeGroupByRegex RepoMatching.comAndroid
                }
            }
        }
    }

    tasks.withType(KotlinCompile).configureEach {
        kotlinOptions.jvmTarget = "17"
        kotlinOptions.allWarningsAsErrors = true
        kotlinOptions.freeCompilerArgs += [
            "-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all-compatibility"
        ]
    }
}

subprojects {
    afterEvaluate {
        if (it.hasProperty('android')) {
            android {
                compileOptions {
                    sourceCompatibility JavaVersion.VERSION_17
                    targetCompatibility JavaVersion.VERSION_17
                }
            }
        }
    }
}

tasks.register('clean', Delete) {
    delete rootProject.layout.buildDirectory
}

detekt {
    input = files("$projectDir/app/src")
    config = files("$projectDir/config/detekt.yml")

    reports {
        html {
            enabled = true
            destination = file("$projectDir/build/reports/detekt.html")
        }
        xml {
            enabled = false
        }
        txt {
            enabled = false
        }
    }
}

tasks.withType(Detekt).configureEach() {
    autoCorrect = true

    exclude "**/test/**"
    exclude "**/androidTest/**"
    exclude "**/build/**"
    exclude "**/resources/**"
    exclude "**/tmp/**"
}

// Apply same path exclusions as for the main task
tasks.withType(DetektCreateBaselineTask).configureEach() {
    exclude "**/test/**"
    exclude "**/androidTest/**"
    exclude "**/build/**"
    exclude "**/resources/**"
    exclude "**/tmp/**"
}

configurations {
    ktlint
}

dependencies {
    ktlint("com.pinterest:ktlint:${Versions.ktlint}") {
        attributes {
            attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
        }
    }

    detekt project(":mozilla-detekt-rules")
    detekt "io.gitlab.arturbosch.detekt:detekt-cli:${Versions.detekt}"
}

tasks.register('ktlint', JavaExec) {
    group = "verification"
    description = "Check Kotlin code style."
    classpath = configurations.ktlint
    mainClass.set("com.pinterest.ktlint.Main")
    args "app/src/**/*.kt", "!**/build/**/*.kt", "--baseline=ktlint-baseline.xml"
}

tasks.register('ktlintFormat', JavaExec) {
    description = "Fix Kotlin code style deviations."
    classpath = configurations.ktlint
    mainClass.set("com.pinterest.ktlint.Main")
    args "-F", "app/src/**/*.kt", "!**/build/**/*.kt", "--baseline=ktlint-baseline.xml"
    jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}

tasks.withType(Detekt.class).configureEach {
    exclude("**/resources/**")
    exclude("**/tmp/**")
}

tasks.register("listRepositories") {
    doLast {
        println "Repositories:"
        project.repositories.each { println "Name: " + it.name + "; url: " + it.url }
    }
}

tasks.register("githubTestDetails", GithubDetailsTask) {
    text = "### [Unit Test Results Fenix]({reportsUrl}/test/testFenixDebugUnitTest/index.html)"
}

tasks.register("githubLintDetektDetails", GithubDetailsTask) {
    text = "### [Detekt Results Fenix]({reportsUrl}/detekt.html)"
}

tasks.register("githubLintAndroidDetails", GithubDetailsTask) {
    text = "### [Android Lint Results Fenix]({reportsUrl}/lint-results-debug.html)"
}

// Task to copy generated baseline profile to the app module nightly variant.
tasks.register("copyBaselineProfile", DefaultTask) {
    doLast {
        File profileFile = fileTree('benchmark/build/outputs') {
            include '**/*baseline-prof.txt'
        }.getSingleFile()
        def destinationPath = Paths.get("app", "src", "nightly", "baselineProfiles", "baseline-prof.txt")
        File destinationDir = destinationPath.toFile().parentFile
        if (!destinationDir.exists()) {
            destinationDir.mkdirs()
        }
        Files.copy(profileFile.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING)
    }
}
