/*
 * Copyright 2020 The Android Open Source Project
 *
 * 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
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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

    dependencies {
        classpath libs.android.tools.build.gradle
        classpath libs.android.gradlePlugin
        classpath libs.kotlin.gradlePlugin

        classpath libs.gradleMavenPublishPlugin

        classpath libs.metalavaGradle

        classpath libs.affectedmoduledetector
    }
}

plugins {
    id "com.diffplug.spotless" version "6.5.2"
    alias(libs.plugins.jetbrains.dokka)
}

apply plugin: 'com.dropbox.affectedmoduledetector'
apply plugin: 'com.diffplug.spotless'

tasks.withType(org.jetbrains.dokka.gradle.DokkaMultiModuleTask).configureEach {
    outputDirectory = rootProject.file('docs/api')
    failOnWarning = true
}

affectedModuleDetector {
    baseDir = "${project.rootDir}"
    pathsAffectingAllModules = [
            "gradle/libs.versions.toml",
    ]
    excludedModules = [
            "sample"
    ]

    logFilename = "output.log"
    logFolder = "${rootProject.buildDir}/affectedModuleDetector"

    String baseRef = findProperty("affected_base_ref")
    // If we have a base ref to diff against, extract the branch name and use it
    if (baseRef != null && !baseRef.isEmpty()) {
        // Remove the prefix from the head.
        // TODO: need to support other types of git refs
        specifiedBranch = baseRef.replace('refs/heads/', '')
        compareFrom = "SpecifiedBranchCommit"
    } else {
        // Otherwise we use the previous commit. This is mostly used for commits to main.
        compareFrom = "PreviousCommit"
    }
}

allprojects {
    repositories {
        google()
        mavenCentral()

        def composeSnapshot = libs.versions.composesnapshot.get()
        if (composeSnapshot.length() > 1) {
            maven { url "https://androidx.dev/snapshots/builds/$composeSnapshot/artifacts/repository/" }
        }
    }
}

subprojects {
    apply plugin: 'com.diffplug.spotless'

    spotless {
        kotlin {
            target "**/*.kt"
            ktlint(libs.versions.ktlint.get())
            licenseHeaderFile rootProject.file('spotless/copyright.txt')
        }

        groovyGradle {
            target '**/*.gradle'
            greclipse().configFile(rootProject.file('spotless/greclipse.properties'))
            licenseHeaderFile rootProject.file('spotless/copyright.txt'),
                    '(buildscript|apply|import|plugins)'
        }
    }

    // Remove all test apps after running UI tests.
    // This is specially important in CI so that test emulators don't run out of space.
    tasks.whenTaskAdded { task ->
        if (task.name == 'connectedDebugAndroidTest') {
            task.finalizedBy 'uninstallDebugAndroidTest'
        }
    }

    configurations.configureEach {
        resolutionStrategy.eachDependency { DependencyResolveDetails details ->
            // Make sure that we're using the Android version of Guava
            if (details.requested.group == 'com.google.guava'
                    && details.requested.module.name == 'guava'
                    && details.requested.version.contains('jre')) {
                details.useVersion details.requested.version.replace('jre', 'android')
            }
        }
    }

    tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { compile ->
        kotlinOptions {
            // Treat all Kotlin warnings as errors
            allWarningsAsErrors = true
            // Set JVM target to 1.8
            jvmTarget = "1.8"
            // Allow use of @OptIn
            freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn"
            // Enable default methods in interfaces
            freeCompilerArgs += "-Xjvm-default=all"
        }
    }

    // Read in the signing.properties file if it is exists
    def signingPropsFile = rootProject.file('release/signing.properties')
    if (signingPropsFile.exists()) {
        def localProperties = new Properties()
        signingPropsFile.withInputStream { is -> localProperties.load(is) }
        localProperties.each { prop ->
            if (prop.key == "signing.secretKeyRingFile") {
                // If this is the key ring, treat it as a relative path
                project.ext.set(prop.key, rootProject.file(prop.value).absolutePath)
            } else {
                project.ext.set(prop.key, prop.value)
            }
        }
    }

    // Must be afterEvaluate or else com.vanniktech.maven.publish will overwrite our
    // dokka and version configuration.
    afterEvaluate {
        if (tasks.findByName('dokkaHtmlPartial') == null) {
            // If dokka isn't enabled on this module, skip
            return
        }

        tasks.named('dokkaHtmlPartial') {
            dokkaSourceSets.configureEach {
                reportUndocumented.set(true)
                skipEmptyPackages.set(true)
                skipDeprecated.set(true)
                jdkVersion.set(8)

                // Add Android SDK packages
                noAndroidSdkLink.set(false)

                // Add samples from :sample module
                samples.from(rootProject.file("sample/src/main/java/"))

                // AndroidX + Compose docs
                externalDocumentationLink {
                    url.set(new URL("https://developer.android.com/reference/"))
                    packageListUrl.set(new URL("https://developer.android.com/reference/androidx/package-list"))
                }
                externalDocumentationLink {
                    url.set(new URL("https://developer.android.com/reference/kotlin/"))
                    packageListUrl.set(new URL("https://developer.android.com/reference/kotlin/androidx/package-list"))
                }

                sourceLink {
                    localDirectory.set(project.file("src/main/java"))
                    // URL showing where the source code can be accessed through the web browser
                    remoteUrl.set(new URL("https://github.com/google/accompanist/blob/main/${project.name}/src/main/java"))
                    // Suffix which is used to append the line number to the URL. Use #L for GitHub
                    remoteLineSuffix.set("#L")
                }
            }
        }
    }

    afterEvaluate {
        def composeSnapshot = libs.versions.composesnapshot.get()
        if (composeSnapshot.length() > 1) {
            // We're depending on a Jetpack Compose snapshot, update the library version name
            // to indicate it's from a Compose snapshot
            def versionName = project.properties.get('VERSION_NAME')
            if (versionName.contains("SNAPSHOT")) {
                version = versionName.replace('-SNAPSHOT', ".compose-${composeSnapshot}-SNAPSHOT")
            }
        }

        if (!version.endsWith('SNAPSHOT')) {
            // If we're not a SNAPSHOT library version, we fail the build if we're relying on
            // any snapshot dependencies
            configurations.configureEach { configuration ->
                configuration.dependencies.configureEach { dependency ->
                    if (dependency instanceof ProjectDependency) {
                        // We don't care about internal project dependencies
                        return
                    }

                    def depVersion = dependency.version
                    if (depVersion != null && depVersion.endsWith('SNAPSHOT')) {
                        throw new IllegalArgumentException(
                                "Using SNAPSHOT dependency with non-SNAPSHOT library version: $dependency"
                        )
                    }
                }
            }
        }
    }
}
