/*
 * Copyright (C) 2017 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
 *
 *      http://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.
 */


import androidx.build.DiffAndDocs
import androidx.build.PublishDocsRulesKt
import androidx.build.gmaven.GMavenVersionChecker
import androidx.build.license.CheckExternalDependencyLicensesTask
import com.android.build.gradle.internal.coverage.JacocoReportTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
import org.gradle.api.logging.configuration.ShowStacktrace

import javax.tools.ToolProvider

def supportRoot = ext.supportRootFolder
if (supportRoot == null) {
    throw new RuntimeException("variable supportRootFolder is not set. you must set it before" +
            " including this script")
}
def init = new Properties()
ext.init = init
rootProject.ext.versionChecker = new GMavenVersionChecker(rootProject.logger)
ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null

apply from: "${supportRoot}/buildSrc/dependencies.gradle"
apply from: "${supportRoot}/buildSrc/build_dependencies.gradle"
apply from: "${supportRoot}/buildSrc/unbundled_check.gradle"


def enableDoclavaAndJDiff(p, dacOptions, rules = []) {
    p.configurations {
        doclava
        jdiff
    }

    p.dependencies {
        doclava build_libs.doclava
        // tools.jar required for com.sun.javadoc
        doclava files(((URLClassLoader) ToolProvider.getSystemToolClassLoader()).getURLs())
        jdiff build_libs.jdiff
        jdiff build_libs.xml_parser_apis
        jdiff build_libs.xerces_impl
    }

    return DiffAndDocs.configureDiffAndDocs(rootProject, supportRootFolder,
            dacOptions, rules)
}

def getFullSdkPath() {
    if (isUnbundledBuild(ext.supportRootFolder)) {
        Properties properties = new Properties()
        File propertiesFile = new File('local.properties')
        if (propertiesFile.exists()) {
            propertiesFile.withInputStream {
                properties.load(it)
            }
        }
        File location = findSdkLocation(properties, supportRootFolder)
        return location.getAbsolutePath()
    } else {
        final String osName = System.getProperty("os.name").toLowerCase();
        final boolean isMacOsX =
                osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx");
        final String platform = isMacOsX ? 'darwin' : 'linux'
        return "${repos.prebuiltsRoot}/fullsdk-${platform}"
    }
}

/**
 * Adapted from com.android.build.gradle.internal.SdkHandler
 */
public static File findSdkLocation(Properties properties, File rootDir) {
    String sdkDirProp = properties.getProperty("sdk.dir");
    if (sdkDirProp != null) {
        File sdk = new File(sdkDirProp);
        if (!sdk.isAbsolute()) {
            sdk = new File(rootDir, sdkDirProp);
        }
        return sdk
    }

    sdkDirProp = properties.getProperty("android.dir");
    if (sdkDirProp != null) {
        return new File(rootDir, sdkDirProp);
    }

    String envVar = System.getenv("ANDROID_HOME");
    if (envVar != null) {
        return new File(envVar);
    }

    String property = System.getProperty("android.home");
    if (property != null) {
        return new File(property);
    }
    return null;
}

def setSdkInLocalPropertiesFile() {
    final File fullSdkPath = file(getFullSdkPath())
    if (fullSdkPath.exists()) {
        project.ext.fullSdkPath = fullSdkPath
        File props = file("local.properties")
        props.write "sdk.dir=${fullSdkPath.getAbsolutePath()}"
        ext.usingFullSdk = true
    } else {
        throw Exception("You are using non ub-supportlib-* checkout. You need to check out "
                + "ub-supportlib-* to work on support library. See go/supportlib for details.")
    }
}

def setupRepoOutAndBuildNumber() {
    // common support repo folder which works well for prebuilts.
    ext.supportRepoOut = ''
    ext.buildNumber = "0"
    /*
     * With the build server you are given two env variables.
     * The OUT_DIR is a temporary directory you can use to put things during the build.
     * The DIST_DIR is where you want to save things from the build.
     *
     * The build server will copy the contents of DIST_DIR to somewhere and make it available.
     */
    if (ext.runningInBuildServer) {
        buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build')
                .getCanonicalFile()
        project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()

        // the build server does not pass the build number so we infer it from the last folder of
        // the dist path.
        ext.buildNumber = project.ext.distDir.getName()

        // the build server should always print out full stack traces for any failures.
        gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS
    } else {
        buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/build")
        project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist")
    }
    subprojects {
        // Change buildDir first so that all plugins pick up the new value.
        project.buildDir = new File("$project.parent.buildDir/../$project.name/build")
    }
    ext.supportRepoOut = new File(buildDir, 'support_repo')
    ext.testApkDistOut = ext.distDir
    ext.testResultsDistDir = new File(distDir, "host-test-reports")
    ext.docsDir = new File(buildDir, 'javadoc')
}

def configureBuildOnServer() {
    def buildOnServerTask = rootProject.tasks.create("buildOnServer")
    rootProject.tasks.whenTaskAdded { task ->
        if ("createArchive".equals(task.name)
                || "createDiffArchive".equals(task.name)
                || "distDocs".equals(task.name)
                || "dejetifyArchive".equals(task.name)
                || CheckExternalDependencyLicensesTask.ROOT_TASK_NAME.equals(task.name)) {
            buildOnServerTask.dependsOn task
        }
    }
    def docsProject = rootProject.findProject(":docs-fake")
    subprojects {
        if (docsProject == project) {
            return
        }
        project.tasks.whenTaskAdded { task ->
            if ("assembleErrorProne".equals(task.name)
                    || "assembleAndroidTest".equals(task.name)
                    || "assembleDebug".equals(task.name)) {
                buildOnServerTask.dependsOn task
            }
        }
    }
    buildOnServerTask.dependsOn createJacocoAntUberJarTask()
    return buildOnServerTask
}

def createJacocoAntUberJarTask() {
    def myJacoco = project.configurations.create('myJacoco')
    project.dependencies.add('myJacoco', build_libs.jacoco_ant)

    return project.tasks.create(
            name: "JacocoAntUberJar",
            type: Jar) {
        inputs.files myJacoco
        from {
            myJacoco
                    .resolvedConfiguration
                    .resolvedArtifacts.collect{ zipTree(it.getFile()) }} {
            // exclude all the signatures the jar might have
            exclude "META-INF/*.SF"
            exclude "META-INF/*.DSA"
            exclude "META-INF/*.RSA"
        }
        destinationDir file(project.distDir)
        archiveName "jacocoant.jar"
    }
}

def configureSubProjects() {
    subprojects {
        repos.addMavenRepositories(repositories)

        // Only modify Android projects.
        if (project.name.equals('noto-emoji-compat')) {
            // disable tests and return
            project.tasks.whenTaskAdded { task ->
                if (task instanceof org.gradle.api.tasks.testing.Test) {
                    task.enabled = false
                }
            }
            return
        }

        project.plugins.whenPluginAdded { plugin ->
            def isAndroidLibrary = "com.android.build.gradle.LibraryPlugin"
                    .equals(plugin.class.name)
            def isAndroidApp = "com.android.build.gradle.AppPlugin".equals(plugin.class.name)

            if (isAndroidLibrary || isAndroidApp) {
                // Enable code coverage for debug builds only if we are not running inside the IDE,
                // since enabling coverage reports breaks the method parameter resolution in the IDE
                // debugger.
                project.android.buildTypes.debug.testCoverageEnabled =
                        !project.hasProperty('android.injected.invoked.from.ide')

                // Copy the class files in a jar to be later used to generate code coverage report
                project.android.testVariants.all { v ->
                    // check if the variant has any source files
                    // and test coverage is enabled
                    if (v.buildType.testCoverageEnabled
                            && v.sourceSets.any { !it.java.sourceFiles.isEmpty() }) {
                        def jarifyTask = project.tasks.create(
                                name: "package${v.name.capitalize()}ClassFilesForCoverageReport",
                                type: Jar) {
                            from v.testedVariant.javaCompile.destinationDir
                            exclude "**/R.class"
                            exclude "**/R\$*.class"
                            exclude "**/BuildConfig.class"
                            destinationDir file(project.distDir)
                            archiveName "${project.name}-${v.baseName}-allclasses.jar"
                        }

                        jarifyTask.dependsOn v.getJavaCompiler()
                        v.assemble.dependsOn jarifyTask
                    }
                }
            }
        }

        // Copy instrumentation test APKs and app APKs into the dist dir
        // For test apks, they are uploaded only if we have java test sources.
        // For regular app apks, they are uploaded only if they have java sources.
        project.tasks.whenTaskAdded { task ->
            if (task.name.startsWith("packageDebug")) {
                def testApk = task.name.contains("AndroidTest")
                task.doLast {
                    def source = testApk ? project.android.sourceSets.androidTest
                            : project.android.sourceSets.main
                    def hasKotlinSources = false
                    if (source.hasProperty('kotlin')) {
                        if (!source.kotlin.files.isEmpty()) {
                            hasKotlinSources = true
                        } else {
                            // kotlin files does not show in java sources due to the *.java filter
                            // so we need to check them manually
                            hasKotlinSources = source.java.sourceDirectoryTrees.any {
                                !fileTree(dir: it.dir, include:'**/*.kt').files.isEmpty()
                            }
                        }
                    }
                    def hasSourceCode = !source.java.sourceFiles.isEmpty() || hasKotlinSources
                    if (task.hasProperty("outputDirectory") && (hasSourceCode || !testApk)) {
                        copy {
                            from(task.outputDirectory)
                            include '*.apk'
                            into(rootProject.ext.testApkDistOut)
                            rename { String fileName ->
                                // Exclude media-compat-test-* modules from existing support library
                                // presubmit tests.
                                if (fileName.contains("media-compat-test")) {
                                    fileName.replace("-debug-androidTest", "")
                                } else {
                                    // multiple modules may have the same name so prefix the name with
                                    // the module's path to ensure it is unique.
                                    // e.g. palette-v7-debug-androidTest.apk becomes
                                    // support-palette-v7_palette-v7-debug-androidTest.apk
                                    "${project.getPath().replace(':', '-').substring(1)}_${fileName}"
                                }
                            }
                        }
                    }
                }
            }
        }

        // copy host side test results to DIST
        project.tasks.whenTaskAdded { task ->
            if (task instanceof org.gradle.api.tasks.testing.Test) {
                def junitReport = task.reports.junitXml
                if (junitReport.enabled) {
                    def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) {
                        destinationDir(testResultsDistDir)
                        // first one is always :, drop it.
                        archiveName("${project.getPath().split(":").join("_").substring(1)}.zip")
                    }
                    if (project.rootProject.ext.runningInBuildServer) {
                        task.ignoreFailures = true
                    }
                    task.finalizedBy zipTask
                    task.doFirst {
                        zipTask.from(junitReport.destination)
                    }
                }
            }
        }

        project.afterEvaluate { p ->
            // remove dependency on the test so that we still get coverage even if some tests fail
            p.tasks.findAll { it instanceof JacocoReportTask }.each { task ->
                def toBeRemoved = new ArrayList()
                def dependencyList = task.taskDependencies.values
                dependencyList.each { dep ->
                    if (dep instanceof String) {
                        def t = tasks.findByName(dep)
                        if (t instanceof DeviceProviderInstrumentTestTask) {
                            toBeRemoved.add(dep)
                            task.mustRunAfter(t)
                        }
                    }
                }
                toBeRemoved.each { dep ->
                    dependencyList.remove(dep)
                }
            }
        }
    }
}

def setupRelease() {
    apply from: "${ext.supportRootFolder}/buildSrc/release.gradle"
}

ext.init.enableDoclavaAndJDiff = this.&enableDoclavaAndJDiff
ext.init.setSdkInLocalPropertiesFile = this.&setSdkInLocalPropertiesFile
ext.init.setupRepoOutAndBuildNumber = this.&setupRepoOutAndBuildNumber
ext.init.setupRelease = this.&setupRelease
ext.init.configureSubProjects = this.&configureSubProjects
ext.init.configureBuildOnServer = this.&configureBuildOnServer
