/*
 * 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 android.support.LibraryVersions
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 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 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 getFullSdkPath() {
    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}"
}

def setSdkInLocalPropertiesFile() {
    ext.buildToolsVersion = '26.0.0'
    final String fullSdkPath = getFullSdkPath();
    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
        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")
        System.setProperty('android.dir', "${supportRootFolder}/../../")
        File props = file("local.properties")
        props.write "android.dir=../../"
        ext.usingFullSdk = false
    }
}

def setupRepoOutAndBuildNumber() {
    // common support repo folder which works well for prebuilts.
    ext.supportRepoOut = ''
    // files in artifactoryRepoOut can be safely copied into a real artifactory.
    ext.artifactoryRepoOut = ''
    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.artifactoryRepoOut =  new File(buildDir, 'artifactory_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)) {
            buildOnServerTask.dependsOn task
        }
    }

    subprojects {
        project.tasks.whenTaskAdded { task ->
            if ("assembleErrorProne".equals(task.name) || "assembleAndroidTest".equals(task.name)) {
                buildOnServerTask.dependsOn task
            }
        }
    }
}

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')
                || project.name.equals('support-media-compat-test-lib')) {
            // disable tests and return
            project.tasks.whenTaskAdded { task ->
                if (task instanceof org.gradle.api.tasks.testing.Test) {
                    task.enabled = false
                }
            }
            return
        }

        project.ext.currentSdk = gradle.ext.currentSdk
        apply plugin: 'maven'

        version = LibraryVersions.SUPPORT_LIBRARY.toString();
        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.name}-${v.baseName}-allclasses.jar"
                        }

                        def collectJacocoAntPackages = project.tasks.create(
                                name: "collectJacocoAntPackages",
                                type: Jar) {
                            inputs.files project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
                            from {
                                project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
                                        .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"
                        }

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

                // Enforce NewApi lint check as fatal.
                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*')
                            }
                        }
                    }

                    // create a release task that produces artifactory friends artifacts
                    // a.k.a. unique versions for snapshots with their maven-metadata files.
                    task artifactoryRelease(type : Upload) {
                        configuration = uploadTask.configuration
                        repositories {
                            mavenDeployer {
                                repository(url: uri("$rootProject.ext.artifactoryRepoOut"))
                                setUniqueVersion(true)
                            }
                        }
                    }

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

                    artifactoryRelease.dependsOn uploadTask

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

        // 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("outputDirectory") && !source.java.sourceFiles.isEmpty()) {
                        copy {
                            from(task.outputDirectory)
                            include '*.apk'
                            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 { 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
