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

buildscript {
    repositories {
        google()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }

    ext {
        // Updating the dependency below throws a 'java.lang.OutOfMemoryError: Metaspace' during build time.
        googleGmsServicesPluginVersion = "4.3.8"
        gradleAndroidBuildToolsPluginVersion = "30.0.3"
        // Need to make many changes before being able to update the gradle plugin version below.
        gradleAndroidToolsPluginVersion = "4.0.2"
        gradleJunitJacocoPluginVersion = "0.16.0"
        gradleDexcountPluginVersion = "3.0.0"
        gradleSpotbugsPluginVersion = "4.7.5"
        gradleAndroidJunit5PluginVersion = "1.8.0.0"
        jacocoVersion = "0.8.7"
        // Updating the dependency below causes a ClassDefNotFound exception with the current CheckStyle implementation
        // in the /eng/ directory.
        qualityReportsPuppycrawlVersion = "8.34"
        qualityReportsJunitVersion = "4.13.2"
    }

    dependencies {
        classpath ("com.android.tools.build:gradle:$gradleAndroidToolsPluginVersion")
        classpath ("de.mannodermaus.gradle.plugins:android-junit5:$gradleAndroidJunit5PluginVersion")
        classpath ("com.getkeepsafe.dexcount:dexcount-gradle-plugin:$gradleDexcountPluginVersion")
        classpath ("com.vanniktech:gradle-android-junit-jacoco-plugin:$gradleJunitJacocoPluginVersion")
        classpath ("gradle.plugin.com.github.spotbugs.snom:spotbugs-gradle-plugin:$gradleSpotbugsPluginVersion")
        classpath ("com.google.gms:google-services:$googleGmsServicesPluginVersion")
    }
}

apply plugin: "com.vanniktech.android.junit.jacoco"

// Configure all client library projects with the standard Android build / publish template.
configure(subprojects.findAll { it.path.startsWith(':sdk:') && it.path.count(':') == 3 }) {
    apply plugin: "com.android.library"
    apply plugin: "de.mannodermaus.android-junit5"
    // https://github.com/KeepSafe/dexcount-gradle-plugin/issues/222#issuecomment-604247658
    // apply plugin: 'com.getkeepsafe.dexcount'.
    apply plugin: 'checkstyle'
    apply plugin: 'com.github.spotbugs'
    apply plugin: "maven-publish"

    group = "com.azure.android"

    android {
        compileSdkVersion 34
        buildToolsVersion ("$gradleAndroidBuildToolsPluginVersion")

        defaultConfig {
            minSdkVersion 15
            targetSdkVersion 34
            testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        }

        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }

        lintOptions {
            lintConfig file("$rootDir/eng/lint.xml")
            htmlReport true
            textReport true
            textOutput 'stdout'
            explainIssues false
            abortOnError true
        }

        packagingOptions {
            exclude 'META-INF/DEPENDENCIES'
            exclude 'META-INF/LICENSE'
            exclude 'META-INF/LICENSE.md'
            exclude 'META-INF/license'
            exclude 'META-INF/NOTICE'
            exclude 'META-INF/NOTICE.md'
            exclude 'META-INF/notice'
            exclude 'META-INF/ASL2.0'
            exclude("META-INF/*.md")
            exclude("META-INF/*.txt")
            exclude("META-INF/*.kotlin_module")
        }

        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
            }

            debug {
                debuggable true
            }
        }

        testOptions {
            unitTests.all {
                jacoco {
                    includeNoLocationClasses = true
                    excludes = ['jdk.internal.*']
                }
            }

            unitTests.includeAndroidResources = true
            unitTests.returnDefaultValues = true
        }
    }

    junitJacoco {
        jacocoVersion = "$jacocoVersion"
    }

    task jacocoTestReport(type: JacocoReport) {
        group = "Reporting"
        description = "Generate Jacoco reports"

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

    // Add dependency to the module containing azure custom checkstyle.
    dependencies {
        checkstyle project(":eng:code-quality-reports")
    }

    task checkstyle(type: Checkstyle) {
        project.ext.checkstyleVersion = '8.29'
        description 'Runs Checkstyle inspection.'
        group = 'Code Quality'
        configDirectory = file("${rootDir}/config/checkstyle")
        configProperties = [samedir: "${rootDir}/config/checkstyle"]
        ignoreFailures false
        showViolations true
        maxWarnings = 0
        classpath = files()
        source 'src/main/java'
    }

    // Check code style after project evaluation.
    afterEvaluate {
        check.dependsOn('checkstyle')
    }

    // Set spotbugs plugin to use SpotBugs.
    dependencies {
        spotbugs 'com.github.spotbugs:spotbugs:4.0.0'
    }

    spotbugs {
        ignoreFailures = false
        showStackTraces = true
        showProgress = true
        effort = "max"
        reportLevel = "Low" // threshold
        reportsDir = file("$buildDir/spotbugs")
        excludeFilter = file("${rootDir}/config/spotbugs/spotbugs-exclude.xml")
    }

    task sourcesJar(type: Jar) {
        from android.sourceSets.main.java.srcDirs
        archiveClassifier.set("sources")
    }

    task javadoc(type: Javadoc) {
        failOnError false
        source = android.sourceSets.main.java.srcDirs
        classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    }

    task javadocJar(type: Jar, dependsOn: javadoc) {
        from javadoc.destinationDir
        archiveClassifier.set("javadoc")
    }

    task updatePackageVersion(type: WriteProperties) {
        if (project.properties["newVersion"])
        {
            outputFile = file('gradle.properties')
            property 'version', project.getProperty("newVersion")
        }
    }

    task retrieveProjectProperties {
        doLast {
            println(project.properties['version'] + '~' +
            project.properties['name'] + '~' +
            project.properties['group']  + '~' +
            project.properties['projectDir'])
        }
    }

    project.afterEvaluate {
        javadoc.classpath += files(android.libraryVariants.collect { variant ->
            variant.javaCompileProvider.get().classpath.files
        })

        publishing {
            publications {
                release(MavenPublication) { -> project
                    from components.release

                    artifact sourcesJar
                    artifact javadocJar

                    pom {
                        name = project.publishName
                        description = project.description
                        url = 'https://github.com/Azure/azure-sdk-for-android'
                        licenses {
                            license {
                                name = 'The MIT License (MIT)'
                                url = 'http://opensource.org/licenses/MIT'
                            }
                        }
                        developers {
                            developer {
                                id = 'microsoft'
                                name = 'Microsoft'
                            }
                        }
                        scm {
                            connection = 'scm:git:https://github.com/Azure/azure-sdk-for-android.git'
                            developerConnection = 'scm:git:https://github.com/Azure/azure-sdk-for-android.git'
                            url = 'https://github.com/Azure/azure-sdk-for-android'
                        }
                    }
                }
            }

            repositories {
                maven {
                    url = "$buildDir/repo/"
                }
            }
        }
    }

    // Used by aggregate-report pipeline to generate .lockfiles
    dependencyLocking {
        lockAllConfigurations()
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
        // org.jetbrains.trove4j:trove4j:20160824.
        maven {
            url 'https://plugins.gradle.org/m2/'
        }
    }

    ext {
        androidxTestVersion = "1.4.0"
        appCompatVersion = "1.2.0"
        azureCommunicationCommonVersion = "1.3.0"
        azureCoreVersion = "1.0.0-beta.14"
        jacksonVersion = "2.12.7" // Do not upgrade to 2.13.0 and above, as it introduced using an API not available in javax.xml.stream:stax-api:1.0-2. See: https://github.com/Azure/azure-sdk-for-android/issues/1017.
        jacksonDatabindVersion = "2.12.7.1" // Need this to be a separate version to include a security fix.
        junitJupiterVersion = "5.7.2"
        mockitoVersion = "4.0.0"
        nimbusJoseJwtTestVersion = "9.15.2"
        okHttpVersion = "3.14.9" // Do not upgrade, newer versions require a higher Android minSdkLevel.
        okioVersion = "1.17.6" // Directly setting this OkHttp dependency as it has a fix for CVE-2023-3635 and we cannot update to a newer version of OkHttp yet. See: https://github.com/square/okio/issues/1323#issuecomment-1742354403
        orgtestngVersion = "7.5.1"
        powerMockVersion = "2.0.9"
        retroFutureVersion = "1.7.4"
        staxApiVersion = "1.0-2" // Need this instead of using the JDK due to: https://stackoverflow.com/a/47371517/1473510.
        slf4jApiVersion = "1.7.32"
        threeTenAbpVersion = "1.3.1"
        threeTenBpVersion = "1.5.1"
        trouterVersion = "0.1.1"
        wireMockVersion = "2.27.2"
        woodstoxVersion = "6.4.0"
    }
}

// Synthesize dependencies for service-level projects so that running a task on a service-level project automatically
// runs it on all sub-projects of that project.
configure(subprojects.findAll { it.path.startsWith(':sdk:') && it.path.count(':') == 2 }) {
    apply plugin: "org.gradle.help-tasks"
    def setupTasks = ["init", "wrapper"]

    project.gradle.startParameter.taskNames.each { task ->
        task = task.split(':').last()
        if (!task.startsWith("-") && !setupTasks.contains(task) && tasks.findByPath(task) == null) {
            tasks.create(task) {
                subprojects.each { dependsOn("$it.name:$task") }
            }
        }
    }
}
