/*
 * 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 com.android.build.gradle.internal.coverage.JacocoPlugin
import com.android.build.gradle.internal.coverage.JacocoReportTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
import com.google.common.base.Charsets
import com.google.common.io.Files

import org.gradle.api.logging.configuration.ShowStacktrace

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
ext.init.debugKeystore = file("${supportRoot}/development/keystore/debug.keystore")

ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null

apply from: "${supportRoot}/buildSrc/dependencies.gradle"
ext.docs = [:]
ext.docs.offline = rootProject.getProperties().containsKey("offlineDocs")
ext.docs.dac = [
        libraryroot: "android/support",
        dataname: "SUPPORT_DATA"
]

def loadDefaultVersions() {
    apply from: "${supportRootFolder}/buildSrc/versions.gradle"
}

def enableDoclavaAndJDiff(p) {
    p.configurations {
        doclava
        jdiff
    }

    p.dependencies {
        doclava project(':doclava')
        jdiff project(':jdiff')
        jdiff libs.xml_parser_apis
        jdiff libs.xerces_impl
    }
    apply from: "${ext.supportRootFolder}/buildSrc/diff_and_docs.gradle"
}

def setSdkInLocalPropertiesFile() {
    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'
    System.setProperty('android.dir', "${supportRootFolder}/../../")
    ext.buildToolsVersion = '26.0.0'
    final String fullSdkPath = "${repos.prebuiltsRoot}/fullsdk-${platform}"
    if (file(fullSdkPath).exists()) {
        gradle.ext.currentSdk = 26
        project.ext.androidJar =
                files("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android.jar")
        project.ext.androidSrcJar =
                file("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android-stubs-src.jar")
        project.ext.androidApiTxt = null
        System.setProperty('android.home', "${repos.prebuiltsRoot}/fullsdk-${platform}")
        File props = file("local.properties")
        props.write "sdk.dir=${fullSdkPath}"
        ext.usingFullSdk = true
    } else {
        gradle.ext.currentSdk = 'current'
        project.ext.androidJar = files("${repos.prebuiltsRoot}/sdk/current/android.jar")
        project.ext.androidSrcJar = null
        project.ext.androidApiTxt = file("${repos.prebuiltsRoot}/sdk/api/26.txt")
        File props = file("local.properties")
        props.write "android.dir=../../"
        ext.usingFullSdk = false
    }
}

def setupRepoOutAndBuildNumber() {
    ext.supportRepoOut = ''
    ext.buildNumber = Integer.toString(ext.extraVersion)

    /*
     * 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 configureSubProjects() {
    // lint every library
    def lintTask = project.tasks.create("lint")
    subprojects {
        repos.addMavenRepositories(repositories)

        // Only modify Android projects.
        if (project.name.equals('doclava')
                || project.name.equals('jdiff')
                || project.name.equals('support-testutils')
                || 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
        }

        // Current SDK is set in studioCompat.gradle.
        project.ext.currentSdk = gradle.ext.currentSdk
        apply plugin: 'maven'

        version = rootProject.ext.supportVersion
        group = 'com.android.support'

        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)
            def isJavaLibrary = "org.gradle.api.plugins.JavaPlugin".equals(plugin.class.name)

            if (isAndroidLibrary || isAndroidApp) {
                project.android.buildToolsVersion = rootProject.buildToolsVersion

                // 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.archivesBaseName}-${v.baseName}-allclasses.jar"
                        }
                        def jacocoAntConfig =
                                project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
                        def jacocoAntArtifacts = jacocoAntConfig.resolvedConfiguration
                                .resolvedArtifacts
                        def version = jacocoAntArtifacts.find { "org.jacoco.ant".equals(it.name) }
                                .moduleVersion.id.version
                        def collectJacocoAntPackages = project.tasks.create(
                                name: "collectJacocoAntPackages",
                                type: Jar) {
                            from(jacocoAntArtifacts.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-" + version + ".jar"
                        }
                        jarifyTask.dependsOn v.getJavaCompiler()
                        v.assemble.dependsOn jarifyTask, collectJacocoAntPackages
                    }
                }

                // Enforce NewApi lint check as fatal.
                project.android.lintOptions.check 'NewApi'
                project.android.lintOptions.fatal 'NewApi'
                lintTask.dependsOn project.lint
            }

            if (isAndroidLibrary || isJavaLibrary) {
                // Add library to the aggregate dependency report.
                task allDeps(type: DependencyReportTask) {}

                project.afterEvaluate {
                    Upload uploadTask = (Upload) project.tasks.uploadArchives;
                    uploadTask.repositories.mavenDeployer {
                        // Disable unique names for SNAPSHOTS so they can be updated in place.
                        setUniqueVersion(false)
                    }
                    uploadTask.doLast {
                        // Remove any invalid maven-metadata.xml files that may have been
                        // created for SNAPSHOT versions that are *not* uniquely versioned.
                        repositories.mavenDeployer.pom*.each { pom ->
                            if (pom.version.endsWith('-SNAPSHOT')) {
                                final File artifactDir = new File(
                                        rootProject.ext.supportRepoOut,
                                        pom.groupId.replace('.', '/')
                                                + '/' + pom.artifactId
                                                + '/' + pom.version)
                                delete fileTree(dir: artifactDir,
                                        include: 'maven-metadata.xml*')
                            }
                        }
                    }

                    uploadTask.repositories.mavenDeployer.pom*.whenConfigured { pom ->
                        pom.dependencies.findAll { dep ->
                            dep.groupId == 'com.android.support' &&
                                    dep.artifactId != 'support-annotations'
                        }*.type = 'aar'
                    }

                    // Before the upload, make sure the repo is ready.
                    uploadTask.dependsOn rootProject.tasks.prepareRepo

                    // Make the mainupload depend on this one.
                    mainUpload.dependsOn uploadTask
                }

            }
        }

        // 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
                    if (task.hasProperty("outputFile") && !source.java.sourceFiles.isEmpty()) {
                        copy {
                            from(task.outputFile)
                            into(rootProject.ext.testApkDistOut)
                            rename { String fileName ->
                                // 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 {
            // The archivesBaseName isn't available initially, so set it now
            def createZipTask = project.tasks.findByName("createSeparateZip")
            if (createZipTask != null) {
                createZipTask.appendix = archivesBaseName
                createZipTask.from versionDir()
            }
        }

        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.loadDefaultVersions = this.&loadDefaultVersions
ext.init.configureSubProjects = this.&configureSubProjects