/*
 * 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.annotations.NonNull
import com.android.annotations.Nullable
import com.android.build.gradle.api.BaseVariant
import com.android.build.gradle.internal.BuildTypeData
import com.android.build.gradle.internal.ConfigurationProvider
import com.android.build.gradle.internal.ProductFlavorData
import com.android.build.gradle.internal.api.ApplicationVariantImpl
import com.android.build.gradle.internal.api.DefaultAndroidSourceSet
import com.android.build.gradle.internal.api.TestVariantImpl
import com.android.build.gradle.internal.dependency.VariantDependencies
import com.android.build.gradle.internal.dsl.BuildTypeDsl
import com.android.build.gradle.internal.dsl.BuildTypeFactory
import com.android.build.gradle.internal.dsl.GroupableProductFlavorDsl
import com.android.build.gradle.internal.dsl.GroupableProductFlavorFactory
import com.android.build.gradle.internal.dsl.SigningConfigDsl
import com.android.build.gradle.internal.dsl.SigningConfigFactory
import com.android.build.gradle.internal.test.PluginHolder
import com.android.build.gradle.internal.variant.ApplicationVariantData
import com.android.build.gradle.internal.variant.BaseVariantData
import com.android.build.gradle.internal.variant.TestVariantData
import com.android.builder.DefaultBuildType
import com.android.builder.VariantConfiguration
import com.android.builder.model.SigningConfig
import com.google.common.collect.ArrayListMultimap
import com.google.common.collect.ListMultimap
import com.google.common.collect.Maps
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.internal.project.ProjectInternal
import org.gradle.api.plugins.BasePlugin
import org.gradle.internal.reflect.Instantiator
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry

import javax.inject.Inject

import static com.android.builder.BuilderConstants.DEBUG
import static com.android.builder.BuilderConstants.INSTRUMENT_TEST
import static com.android.builder.BuilderConstants.LINT
import static com.android.builder.BuilderConstants.RELEASE
import static com.android.builder.BuilderConstants.UI_TEST

/**
 * Gradle plugin class for 'application' projects.
 */
class AppPlugin extends com.android.build.gradle.BasePlugin implements Plugin<Project> {
    static PluginHolder pluginHolder;

    final Map<String, BuildTypeData> buildTypes = [:]
    final Map<String, ProductFlavorData<GroupableProductFlavorDsl>> productFlavors = [:]
    final Map<String, SigningConfig> signingConfigs = [:]

    AppExtension extension

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

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

        // This is for testing.
        if (pluginHolder != null) {
            pluginHolder.plugin = this;
        }

        def buildTypeContainer = project.container(DefaultBuildType,
                new BuildTypeFactory(instantiator,  project.fileResolver))
        def productFlavorContainer = project.container(GroupableProductFlavorDsl,
                new GroupableProductFlavorFactory(instantiator, project.fileResolver))
        def signingConfigContainer = project.container(SigningConfig,
                new SigningConfigFactory(instantiator))

        extension = project.extensions.create('android', AppExtension,
                this, (ProjectInternal) project, instantiator,
                buildTypeContainer, productFlavorContainer, signingConfigContainer)
        setBaseExtension(extension)

        // map the whenObjectAdded callbacks on the containers.
        signingConfigContainer.whenObjectAdded { SigningConfig signingConfig ->
            SigningConfigDsl signingConfigDsl = (SigningConfigDsl) signingConfig
            signingConfigs[signingConfigDsl.name] = signingConfig
        }

        buildTypeContainer.whenObjectAdded { DefaultBuildType buildType ->
            ((BuildTypeDsl)buildType).init(signingConfigContainer.getByName(DEBUG))
            addBuildType(buildType)
        }

        productFlavorContainer.whenObjectAdded { GroupableProductFlavorDsl productFlavor ->
            addProductFlavor(productFlavor)
        }

        // create default Objects, signingConfig first as its used by the BuildTypes.
        signingConfigContainer.create(DEBUG)
        buildTypeContainer.create(DEBUG)
        buildTypeContainer.create(RELEASE)

        // map whenObjectRemoved on the containers to throw an exception.
        signingConfigContainer.whenObjectRemoved {
            throw new UnsupportedOperationException("Removing signingConfigs is not supported.")
        }
        buildTypeContainer.whenObjectRemoved {
            throw new UnsupportedOperationException("Removing build types is not supported.")
        }
        productFlavorContainer.whenObjectRemoved {
            throw new UnsupportedOperationException("Removing product flavors is not supported.")
        }
    }

    /**
     * Adds new BuildType, creating a BuildTypeData, and the associated source set,
     * and adding it to the map.
     * @param buildType the build type.
     */
    private void addBuildType(DefaultBuildType buildType) {
        String name = buildType.name
        checkName(name, "BuildType")

        if (productFlavors.containsKey(name)) {
            throw new RuntimeException("BuildType names cannot collide with ProductFlavor names")
        }

        def sourceSet = extension.sourceSetsContainer.create(name)

        BuildTypeData buildTypeData = new BuildTypeData(buildType, sourceSet, project)
        project.tasks.assemble.dependsOn buildTypeData.assembleTask

        buildTypes[name] = buildTypeData
    }

    /**
     * Adds a new ProductFlavor, creating a ProductFlavorData and associated source sets,
     * and adding it to the map.
     *
     * @param productFlavor the product flavor
     */
    private void addProductFlavor(GroupableProductFlavorDsl productFlavor) {
        String name = productFlavor.name
        checkName(name, "ProductFlavor")

        if (buildTypes.containsKey(name)) {
            throw new RuntimeException("ProductFlavor names cannot collide with BuildType names")
        }

        def mainSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(productFlavor.name)
        String testName = "${INSTRUMENT_TEST}${productFlavor.name.capitalize()}"
        def testSourceSet = (DefaultAndroidSourceSet) extension.sourceSetsContainer.create(testName)

        ProductFlavorData<GroupableProductFlavorDsl> productFlavorData =
                new ProductFlavorData<GroupableProductFlavorDsl>(
                        productFlavor, mainSourceSet, testSourceSet, project)

        productFlavors[productFlavor.name] = productFlavorData
    }

    private static void checkName(String name, String displayName) {
        if (name.startsWith(INSTRUMENT_TEST)) {
            throw new RuntimeException(
                    "${displayName} names cannot start with '${INSTRUMENT_TEST}'")
        }

        if (name.startsWith(UI_TEST)) {
            throw new RuntimeException(
                    "${displayName} names cannot start with '${UI_TEST}'")
        }

        if (LINT.equals(name)) {
            throw new RuntimeException("${displayName} names cannot be ${LINT}")
        }
    }

    /**
     * Task creation entry point.
     */
    @Override
    protected void doCreateAndroidTasks() {
        if (productFlavors.isEmpty()) {
            createTasksForDefaultBuild()
        } else {
            // there'll be more than one test app, so we need a top level assembleTest
            assembleTest = project.tasks.create("assembleTest")
            assembleTest.group = BasePlugin.BUILD_GROUP
            assembleTest.description = "Assembles all the Test applications"

            // check whether we have multi flavor builds
            if (extension.flavorGroupList == null || extension.flavorGroupList.size() < 2) {
                productFlavors.values().each { ProductFlavorData productFlavorData ->
                    createTasksForFlavoredBuild(productFlavorData)
                }
            } else {
                // need to group the flavor per group.
                // First a map of group -> list(ProductFlavor)
                ArrayListMultimap<String, ProductFlavorData<GroupableProductFlavorDsl>> map = ArrayListMultimap.create();
                productFlavors.values().each { ProductFlavorData<GroupableProductFlavorDsl> productFlavorData ->
                    def flavor = productFlavorData.productFlavor
                    if (flavor.flavorGroup == null) {
                        throw new RuntimeException(
                                "Flavor ${flavor.name} has no flavor group.")
                    }
                    if (!extension.flavorGroupList.contains(flavor.flavorGroup)) {
                        throw new RuntimeException(
                                "Flavor ${flavor.name} has unknown group ${flavor.flavorGroup}.")
                    }

                    map.put(flavor.flavorGroup, productFlavorData)
                }

                // now we use the flavor groups to generate an ordered array of flavor to use
                ProductFlavorData[] array = new ProductFlavorData[extension.flavorGroupList.size()]
                createTasksForMultiFlavoredBuilds(array, 0, map)
            }
        }

        // create the test tasks.
        createCheckTasks(!productFlavors.isEmpty(), false /*isLibrary*/)

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

    /**
     * Creates the tasks for multi-flavor builds.
     *
     * This recursively fills the array of ProductFlavorData (in the order defined
     * in extension.flavorGroupList), creating all possible combination.
     *
     * @param datas the arrays to fill
     * @param i the current index to fill
     * @param map the map of group -> list(ProductFlavor)
     * @return
     */
    private createTasksForMultiFlavoredBuilds(ProductFlavorData[] datas, int i,
                                              ListMultimap<String, ? extends ProductFlavorData> map) {
        if (i == datas.length) {
            createTasksForFlavoredBuild(datas)
            return
        }

        // fill the array at the current index.
        // get the group name that matches the index we are filling.
        def group = extension.flavorGroupList.get(i)

        // from our map, get all the possible flavors in that group.
        def flavorList = map.get(group)

        // loop on all the flavors to add them to the current index and recursively fill the next
        // indices.
        for (ProductFlavorData flavor : flavorList) {
            datas[i] = flavor
            createTasksForMultiFlavoredBuilds(datas, (int) i + 1, map)
        }
    }

    /**
     * Creates Tasks for non-flavored build. This means assembleDebug, assembleRelease, and other
     * assemble<Type> are directly building the <type> build instead of all build of the given
     * <type>.
     */
    private createTasksForDefaultBuild() {
        BuildTypeData testData = buildTypes[extension.testBuildType]
        if (testData == null) {
            throw new RuntimeException("Test Build Type '$extension.testBuildType' does not exist.")
        }

        ApplicationVariantData testedVariantData = null

        ProductFlavorData defaultConfigData = getDefaultConfigData();

        for (BuildTypeData buildTypeData : buildTypes.values()) {
            def variantConfig = new VariantConfiguration(
                    defaultConfigData.productFlavor, defaultConfigData.sourceSet,
                    buildTypeData.buildType, buildTypeData.sourceSet, project.name)

            // create the variant and get its internal storage object.
            ApplicationVariantData appVariantData = new ApplicationVariantData(variantConfig)
            VariantDependencies variantDep = VariantDependencies.compute(
                    project, appVariantData.name, buildTypeData, defaultConfigData.mainProvider)
            appVariantData.setVariantDependency(variantDep)

            variantDataList.add(appVariantData)

            if (buildTypeData == testData) {
                testedVariantData = appVariantData
            }
        }

        assert testedVariantData != null

        // handle the test variant
        def testVariantConfig = new VariantConfiguration(
                defaultConfigData.productFlavor, defaultConfigData.testSourceSet,
                testData.buildType, null,
                VariantConfiguration.Type.TEST, testedVariantData.variantConfiguration,
                project.name)

        // create the internal storage for this variant.
        def testVariantData = new TestVariantData(testVariantConfig, testedVariantData)
        variantDataList.add(testVariantData)
        // link the testVariant to the tested variant in the other direction
        testedVariantData.setTestVariantData(testVariantData);

        // dependencies for the test variant
        VariantDependencies variantDep = VariantDependencies.compute(
                project, testVariantData.name, defaultConfigData.testProvider)
        testVariantData.setVariantDependency(variantDep)

        // now loop on the VariantDependency and resolve them, and create the tasks
        // for each variant
        for (BaseVariantData variantData : variantDataList) {
            resolveDependencies(variantData.variantDependency)
            variantData.variantConfiguration.setDependencies(variantData.variantDependency)

            if (variantData instanceof ApplicationVariantData) {
                createApplicationVariant(
                        (ApplicationVariantData) variantData,
                        buildTypes[variantData.variantConfiguration.buildType.name].assembleTask)

            } else if (variantData instanceof TestVariantData) {
                testVariantData = (TestVariantData) variantData
                createTestApkTasks(testVariantData,
                        (BaseVariantData) 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 ApplicationVariantData) {
                ApplicationVariantData appVariantData = (ApplicationVariantData) variantData
                createVariantApiObjects(map, appVariantData, appVariantData.testVariantData)

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

    private void createVariantApiObjects(@NonNull Map<BaseVariantData, BaseVariant> map,
                                         @NonNull ApplicationVariantData appVariantData,
                                         @Nullable TestVariantData testVariantData) {
        ApplicationVariantImpl appVariant = instantiator.newInstance(
                ApplicationVariantImpl.class, appVariantData)

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

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

        extension.addApplicationVariant(appVariant)
        map.put(appVariantData, appVariant)

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

    /**
     * Creates Task for a given flavor. This will create tasks for all build types for the given
     * flavor.
     * @param flavorDataList the flavor(s) to build.
     */
    private createTasksForFlavoredBuild(ProductFlavorData... flavorDataList) {

        BuildTypeData testData = buildTypes[extension.testBuildType]
        if (testData == null) {
            throw new RuntimeException("Test Build Type '$extension.testBuildType' does not exist.")
        }

        // because this method is called multiple times, we need to keep track
        // of the variantData only for this call.
        final List<BaseVariantData> localVariantDataList = []

        ApplicationVariantData testedVariantData = null

        // assembleTask for this flavor(group)
        def assembleTask = createAssembleTask(flavorDataList)
        project.tasks.assemble.dependsOn assembleTask

        for (BuildTypeData buildTypeData : buildTypes.values()) {
            /// add the container of dependencies
            // the order of the libraries is important. In descending order:
            // build types, flavors, defaultConfig.
            List<ConfigurationProvider> variantProviders = []
            variantProviders.add(buildTypeData)

            VariantConfiguration variantConfig = new VariantConfiguration(
                    extension.defaultConfig, getDefaultConfigData().sourceSet,
                    buildTypeData.buildType, buildTypeData.sourceSet, project.name)

            for (ProductFlavorData data : flavorDataList) {
                variantConfig.addProductFlavor(data.productFlavor, data.sourceSet)
                variantProviders.add(data.mainProvider)
            }

            // now add the defaultConfig
            variantProviders.add(defaultConfigData.mainProvider)

            // create the variant and get its internal storage object.
            ApplicationVariantData appVariantData = new ApplicationVariantData(variantConfig)
            VariantDependencies variantDep = VariantDependencies.compute(
                    project, appVariantData.name,
                    variantProviders.toArray(new ConfigurationProvider[variantProviders.size()]))
            appVariantData.setVariantDependency(variantDep)

            localVariantDataList.add(appVariantData)

            if (buildTypeData == testData) {
                testedVariantData = appVariantData
            }
        }

        assert testedVariantData != null

        // handle test variant
        VariantConfiguration testVariantConfig = new VariantConfiguration(
                extension.defaultConfig, getDefaultConfigData().testSourceSet,
                testData.buildType, null,
                VariantConfiguration.Type.TEST,
                testedVariantData.variantConfiguration, project.name)

        /// add the container of dependencies
        // the order of the libraries is important. In descending order:
        // flavors, defaultConfig. No build type for tests
        List<ConfigurationProvider> testVariantProviders = []

        for (ProductFlavorData data : flavorDataList) {
            testVariantConfig.addProductFlavor(data.productFlavor, data.testSourceSet)
            testVariantProviders.add(data.testProvider)
        }

        // now add the default config
        testVariantProviders.add(defaultConfigData.testProvider)

        // create the internal storage for this variant.
        TestVariantData testVariantData = new TestVariantData(testVariantConfig, testedVariantData)
        localVariantDataList.add(testVariantData)
        // link the testVariant to the tested variant in the other direction
        testedVariantData.setTestVariantData(testVariantData);

        // dependencies for the test variant
        VariantDependencies variantDep = VariantDependencies.compute(
                project, testVariantData.name,
                testVariantProviders.toArray(new ConfigurationProvider[testVariantProviders.size()]))
        testVariantData.setVariantDependency(variantDep)

        // now loop on the VariantDependency and resolve them, and create the tasks
        // for each variant
        for (BaseVariantData variantData : localVariantDataList) {
            resolveDependencies(variantData.variantDependency)
            variantData.variantConfiguration.setDependencies(variantData.variantDependency)

            if (variantData instanceof ApplicationVariantData) {
                BuildTypeData buildTypeData = buildTypes[variantData.variantConfiguration.buildType.name]
                createApplicationVariant((ApplicationVariantData) variantData, null)

                buildTypeData.assembleTask.dependsOn variantData.assembleTask
                assembleTask.dependsOn variantData.assembleTask

            } else if (variantData instanceof TestVariantData) {
                testVariantData = (TestVariantData) variantData
                createTestApkTasks(testVariantData,
                        (BaseVariantData) testVariantData.testedVariantData)
            }

            variantDataList.add(variantData)
        }
    }

    private Task createAssembleTask(ProductFlavorData[] flavorDataList) {
        String name = ProductFlavorData.getFlavoredName(flavorDataList, true)

        def assembleTask = project.tasks.create("assemble${name}")
        assembleTask.description = "Assembles all builds for flavor ${name}"
        assembleTask.group = "Build"

        return assembleTask
    }

    /**
     * Creates an ApplicationVariantData and its tasks for a given variant configuration.
     * @param variantConfig the non-null variant configuration.
     * @param assembleTask an optional assembleTask to be used. If null, a new one is created.
     * @param configDependencies a non null list of dependencies for this variant.
     * @return
     */
    @NonNull
    private void createApplicationVariant(
            @NonNull ApplicationVariantData variant,
            @Nullable Task assembleTask) {

        createPrepareDependenciesTask(variant)

        // Add a task to process the manifest(s)
        createProcessManifestTask(variant, "manifests")

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

        // Add a task to merge the resource folders
        createMergeResourcesTask(variant, true /*process9Patch*/)

        // Add a task to merge the asset folders
        createMergeAssetsTask(variant, null /*default location*/, true /*includeDependencies*/)

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

        // Add a task to generate resource source files
        createProcessResTask(variant)

        // Add a task to process the java resources
        createProcessJavaResTask(variant)

        createAidlTask(variant)

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

        addPackageTasks(variant, assembleTask)
    }
}
