/*
 * Copyright (C) 2012 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.
 */
package com.android.build.gradle
import com.android.SdkConstants
import com.android.annotations.NonNull
import com.android.annotations.Nullable
import com.android.build.gradle.api.AndroidSourceSet
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.internal.BuildTypeData
import com.android.build.gradle.internal.ProductFlavorData
import com.android.build.gradle.internal.api.DefaultAndroidSourceSet
import com.android.build.gradle.internal.api.LibraryVariantImpl
import com.android.build.gradle.internal.api.TestVariantImpl
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.tasks.MergeFileTask
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.LibraryVariantData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.build.gradle.tasks.MergeResources
import com.android.builder.BuilderConstants
import com.android.builder.DefaultBuildType
import com.android.builder.VariantConfiguration
import com.android.builder.dependency.DependencyContainer
import com.android.builder.dependency.JarDependency
import com.android.builder.dependency.LibraryBundle
import com.android.builder.dependency.LibraryDependency
import com.android.builder.dependency.ManifestDependency
import com.android.builder.model.AndroidLibrary
import com.google.common.collect.Maps
import com.google.common.collect.Sets
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.MavenPlugin
import org.gradle.api.tasks.Copy
import org.gradle.api.tasks.Sync
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.bundling.Zip
import org.gradle.internal.reflect.Instantiator
import org.gradle.tooling.BuildException
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry

import javax.inject.Inject
/**
 * Gradle plugin class for 'library' projects.
 */
public class LibraryPlugin extends BasePlugin implements Plugin<Project> {

    LibraryExtension extension
    BuildTypeData debugBuildTypeData
    BuildTypeData releaseBuildTypeData

    @Inject
    public LibraryPlugin(Instantiator instantiator, ToolingModelBuilderRegistry registry) {
        super(instantiator, registry)
    }

    @Override
    void apply(Project project) {
        super.apply(project)

        extension = project.extensions.create('android', LibraryExtension,
                this, (ProjectInternal) project, instantiator)
        setBaseExtension(extension);

        // create the source sets for the build type.
        // the ones for the main product flavors are handled by the base plugin.
        DefaultAndroidSourceSet debugSourceSet =
            (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(BuilderConstants.DEBUG)
        DefaultAndroidSourceSet releaseSourceSet =
            (DefaultAndroidSourceSet) extension.sourceSetsContainer.maybeCreate(BuilderConstants.RELEASE)

        debugBuildTypeData = new BuildTypeData(extension.debug, debugSourceSet, project)
        releaseBuildTypeData = new BuildTypeData(extension.release, releaseSourceSet, project)
        project.tasks.assemble.dependsOn debugBuildTypeData.assembleTask
        project.tasks.assemble.dependsOn releaseBuildTypeData.assembleTask

        createConfigurations(releaseSourceSet)
    }

    void createConfigurations(AndroidSourceSet releaseSourceSet) {
        // The library artifact is published for the "default" configuration so we make
        // sure "default" extends from the actual configuration used for building.
        project.configurations["default"].extendsFrom(
                project.configurations[mainSourceSet.getPackageConfigurationName()])
        project.configurations["default"].extendsFrom(
                project.configurations[releaseSourceSet.getPackageConfigurationName()])

        project.plugins.withType(MavenPlugin) {
            project.conf2ScopeMappings.addMapping(300,
                    project.configurations[mainSourceSet.getCompileConfigurationName()],
                    "compile")
            project.conf2ScopeMappings.addMapping(300,
                    project.configurations[releaseSourceSet.getCompileConfigurationName()],
                    "compile")
            // TODO -- figure out the package configuration
//            project.conf2ScopeMappings.addMapping(300,
//                    project.configurations[mainSourceSet.getPackageConfigurationName()],
//                    "runtime")
//            project.conf2ScopeMappings.addMapping(300,
//                    project.configurations[releaseSourceSet.getPackageConfigurationName()],
//                    "runtime")
        }
    }

    @Override
    protected void doCreateAndroidTasks() {
        ProductFlavorData defaultConfigData = getDefaultConfigData()
        VariantDependencies variantDep

        LibraryVariantData debugVariantData = createLibVariant(defaultConfigData,
                debugBuildTypeData)
        LibraryVariantData releaseVariantData = createLibVariant(defaultConfigData,
                releaseBuildTypeData)

        // Add a compile lint task before library is bundled
        createLintCompileTask()

        // Need to create the tasks for these before doing the test variant as it
        // references the debug variant and its output
        createLibraryVariant(debugVariantData, false)
        createLibraryVariant(releaseVariantData, true)

        VariantConfiguration testVariantConfig = new VariantConfiguration(
                defaultConfigData.productFlavor,
                defaultConfigData.testSourceSet,
                debugBuildTypeData.buildType,
                null,
                VariantConfiguration.Type.TEST,
                debugVariantData.variantConfiguration)

        TestVariantData testVariantData = new TestVariantData(testVariantConfig, debugVariantData)
        // link the testVariant to the tested variant in the other direction
        debugVariantData.setTestVariantData(testVariantData);

        // dependencies for the test variant
        variantDep = VariantDependencies.compute(project,
                testVariantData.variantConfiguration.fullName,
                defaultConfigData.testProvider, debugVariantData.variantDependency)
        testVariantData.setVariantDependency(variantDep)

        variantDataList.add(testVariantData)

        createTestVariant(testVariantData, debugVariantData)

        // create the lint tasks.
        createLintTasks()

        // create the test tasks.
        createCheckTasks(false /*hasFlavors*/, true /*isLibrary*/)

        // Create the variant API objects after the tasks have been created!
        createApiObjects()
    }

    protected LibraryVariantData createLibVariant(@NonNull ProductFlavorData configData,
                                                  @NonNull BuildTypeData buildTypeData) {
        VariantConfiguration variantConfig = new VariantConfiguration(
                configData.productFlavor,
                configData.sourceSet,
                buildTypeData.buildType,
                buildTypeData.sourceSet,
                VariantConfiguration.Type.LIBRARY)

        LibraryVariantData variantData = new LibraryVariantData(variantConfig)

        VariantDependencies debugVariantDep = VariantDependencies.compute(
                project, variantData.variantConfiguration.fullName,
                buildTypeData, configData.mainProvider)
        variantData.setVariantDependency(debugVariantDep)

        variantDataList.add(variantData)

        return variantData
    }

    private void createLibraryVariant(@NonNull LibraryVariantData variantData,
                                      boolean publishArtifact) {
        resolveDependencies(variantData.variantDependency)
        variantData.variantConfiguration.setDependencies(variantData.variantDependency)

        VariantConfiguration variantConfig = variantData.variantConfiguration
        DefaultBuildType buildType = variantConfig.buildType

        createAnchorTasks(variantData)

        // Add a task to process the manifest(s)
        createProcessManifestTask(variantData, DIR_BUNDLES)

        // Add a task to compile renderscript files.
        createRenderscriptTask(variantData)

        // Add a task to merge the resource folders, including the libraries, in order to
        // generate the R.txt file with all the symbols, including the ones from the dependencies.
        createMergeResourcesTask(variantData, false /*process9Patch*/)

        // Create another merge task to only merge the resources from this libraries and not
        // the dependencies. This is what gets packaged in the aar.
        MergeResources packageRes = basicCreateMergeResourcesTask(variantData,
                "package",
                "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/res",
                false /*includeDependencies*/,
                false /*process9Patch*/)

        // Add a task to merge the assets folders
        createMergeAssetsTask(variantData,
                "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/assets",
                false /*includeDependencies*/)

        // Add a task to create the BuildConfig class
        createBuildConfigTask(variantData)

        // Add a task to generate resource source files, directing the location
        // of the r.txt file to be directly in the bundle.
        createProcessResTask(variantData,
                "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}")

        // process java resources
        createProcessJavaResTask(variantData)

        createAidlTask(variantData)

        // Add a compile task
        createCompileTask(variantData, null/*testedVariant*/)

        // Add NDK tasks
        createNdkTasks(
                variantData,
                { project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/jni") });

        // package the aidl files into the bundle folder
        Sync packageAidl = project.tasks.create(
                "package${variantData.variantConfiguration.fullName.capitalize()}Aidl",
                Sync)
        // packageAidl from 3 sources. the order is important to make sure the override works well.
        packageAidl.from(variantConfig.aidlSourceList).include("**/*.aidl")
        packageAidl.into(project.file(
                "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.FD_AIDL"))

        // package the renderscript header files files into the bundle folder
        Sync packageRenderscript = project.tasks.create(
                "package${variantData.variantConfiguration.fullName.capitalize()}Renderscript",
                Sync)
        // package from 3 sources. the order is important to make sure the override works well.
        packageRenderscript.from(variantConfig.renderscriptSourceList).include("**/*.rsh")
        packageRenderscript.into(project.file(
                "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.FD_RENDERSCRIPT"))

        // merge consumer proguard files from different build types and flavors
        MergeFileTask mergeProGuardFileTask = project.tasks.create(
                "merge${variantData.variantConfiguration.fullName.capitalize()}ProguardFiles",
                MergeFileTask)
        mergeProGuardFileTask.conventionMapping.inputFiles = {
            project.files(variantConfig.getConsumerProguardFiles()).files }
        mergeProGuardFileTask.conventionMapping.outputFile = {
            project.file(
                    "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$LibraryBundle.FN_PROGUARD_TXT")
        }

        // copy lint.jar into the bundle folder
        Copy lintCopy = project.tasks.create(
                "copy${variantData.variantConfiguration.fullName.capitalize()}Lint",
                Copy)
        lintCopy.dependsOn lintCompile
        lintCopy.from("$project.buildDir/lint/lint.jar")
        lintCopy.into("$project.buildDir/$DIR_BUNDLES/$variantData.variantConfiguration.dirName")

        Zip bundle = project.tasks.create(
                "bundle${variantData.variantConfiguration.fullName.capitalize()}",
                Zip)

        if (variantConfig.buildType.runProguard) {
            // run proguard on output of compile task
            createProguardTasks(variantData, null)

            // hack since bundle can't depend on variantData.proguardTask
            mergeProGuardFileTask.dependsOn variantData.proguardTask

            bundle.dependsOn packageRes, packageAidl, packageRenderscript, mergeProGuardFileTask, lintCopy, variantData.ndkCompileTask
        } else {
            Sync packageLocalJar = project.tasks.create(
                    "package${variantData.variantConfiguration.fullName.capitalize()}LocalJar",
                    Sync)
            packageLocalJar.from(getLocalJarFileList(variantData.variantDependency))
            packageLocalJar.into(project.file(
                    "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}/$SdkConstants.LIBS_FOLDER"))

            // jar the classes.
            Jar jar = project.tasks.create("package${buildType.name.capitalize()}Jar", Jar);
            jar.dependsOn variantData.javaCompileTask, variantData.processJavaResourcesTask
            jar.from(variantData.javaCompileTask.outputs);
            jar.from(variantData.processJavaResourcesTask.destinationDir)

            jar.destinationDir = project.file(
                    "$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}")
            jar.archiveName = "classes.jar"

            String packageName = variantConfig.getPackageFromManifest()
            if (packageName == null) {
                throw new BuildException("Failed to read manifest", null)
            }
            packageName = packageName.replace('.', '/');

            jar.exclude(packageName + "/R.class")
            jar.exclude(packageName + "/R\$*.class")
            jar.exclude(packageName + "/Manifest.class")
            jar.exclude(packageName + "/Manifest\$*.class")
            jar.exclude(packageName + "/BuildConfig.class")

            bundle.dependsOn packageRes, jar, packageAidl, packageRenderscript, packageLocalJar,
                    mergeProGuardFileTask, lintCopy, variantData.ndkCompileTask
        }

        bundle.setDescription("Assembles a bundle containing the library in ${variantData.variantConfiguration.fullName.capitalize()}.");
        bundle.destinationDir = project.file("$project.buildDir/libs")
        bundle.extension = BuilderConstants.EXT_LIB_ARCHIVE
        if (variantData.variantConfiguration.baseName != BuilderConstants.RELEASE) {
            bundle.classifier = variantData.variantConfiguration.baseName
        }
        bundle.from(project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}"))

        variantData.packageLibTask = bundle
        variantData.outputFile = bundle.archivePath

        if (publishArtifact) {
            // add the artifact that will be published
            project.artifacts.add("default", bundle)
            releaseBuildTypeData.assembleTask.dependsOn bundle
        } else {
            debugBuildTypeData.assembleTask.dependsOn bundle
        }

        variantData.assembleTask = bundle

        // configure the variant to be testable.
        variantConfig.output = new LibraryBundle(
                bundle.archivePath,
                project.file("$project.buildDir/$DIR_BUNDLES/${variantData.variantConfiguration.dirName}"),
                variantData.getName()) {

            @Nullable
            @Override
            String getProject() {
                return LibraryPlugin.this.project.path
            }

            @NonNull
            @Override
            List<LibraryDependency> getDependencies() {
                return variantConfig.directLibraries
            }

            @NonNull
            @Override
            List<? extends AndroidLibrary> getLibraryDependencies() {
                return variantConfig.directLibraries
            }

            @NonNull
            @Override
            List<ManifestDependency> getManifestDependencies() {
                return variantConfig.directLibraries
            }
        };
    }

    static Object[] getLocalJarFileList(DependencyContainer dependencyContainer) {
        Set<File> files = Sets.newHashSet()
        for (JarDependency jarDependency : dependencyContainer.localDependencies) {
            files.add(jarDependency.jarFile)
        }

        return files.toArray()
    }

    private void createTestVariant(@NonNull TestVariantData testVariantData,
                                   @NonNull LibraryVariantData testedVariantData) {

        resolveDependencies(testVariantData.variantDependency)
        testVariantData.variantConfiguration.setDependencies(testVariantData.variantDependency)

        createTestApkTasks(testVariantData, testedVariantData)
    }

    protected void createApiObjects() {
        // we always want to have the test/tested objects created at the same time
        // so that dynamic closure call on add can have referenced objects created.
        // This means some objects are created before they are processed from the loop,
        // so we store whether we have processed them or not.
        Map<BaseVariantData, BaseVariant> map = Maps.newHashMap()
        for (BaseVariantData variantData : variantDataList) {
            if (map.get(variantData) != null) {
                continue
            }

            if (variantData instanceof LibraryVariantData) {
                LibraryVariantData libVariantData = (LibraryVariantData) variantData
                createVariantApiObjects(map, libVariantData, libVariantData.testVariantData)

            } else if (variantData instanceof TestVariantData) {
                TestVariantData testVariantData = (TestVariantData) variantData
                createVariantApiObjects(map,
                        (LibraryVariantData) testVariantData.testedVariantData,
                        testVariantData)
            }
        }
    }

    private void createVariantApiObjects(@NonNull Map<BaseVariantData, BaseVariant> map,
                                         @NonNull LibraryVariantData libVariantData,
                                         @Nullable TestVariantData testVariantData) {
        LibraryVariantImpl libVariant = instantiator.newInstance(
                LibraryVariantImpl.class, libVariantData)

        TestVariantImpl testVariant = null;
        if (testVariantData != null) {
            testVariant = instantiator.newInstance(TestVariantImpl.class, testVariantData)
        }

        if (libVariant != null && testVariant != null) {
            libVariant.setTestVariant(testVariant)
            testVariant.setTestedVariant(libVariant)
        }

        extension.addLibraryVariant(libVariant)
        map.put(libVariantData, libVariant)

        if (testVariant != null) {
            extension.addTestVariant(testVariant)
            map.put(testVariantData, testVariant)
        }
    }
}
