/*
 * Copyright (C) 2015 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.internal;

import static com.android.SdkConstants.FN_PUBLIC_TXT;
import static com.android.build.api.transform.QualifiedContent.DefaultContentType.RESOURCES;
import static com.android.build.gradle.internal.pipeline.ExtendedContentType.NATIVE_LIBS;
import static com.android.build.gradle.internal.scope.InternalArtifactType.JAVAC;

import android.databinding.tool.DataBindingBuilder;
import com.android.annotations.NonNull;
import com.android.build.api.transform.QualifiedContent;
import com.android.build.api.transform.QualifiedContent.Scope;
import com.android.build.api.transform.QualifiedContent.ScopeType;
import com.android.build.api.transform.Transform;
import com.android.build.gradle.AndroidConfig;
import com.android.build.gradle.internal.core.GradleVariantConfiguration;
import com.android.build.gradle.internal.pipeline.OriginalStream;
import com.android.build.gradle.internal.pipeline.TransformManager;
import com.android.build.gradle.internal.publishing.AndroidArtifacts;
import com.android.build.gradle.internal.scope.AnchorOutputType;
import com.android.build.gradle.internal.scope.BuildArtifactsHolder;
import com.android.build.gradle.internal.scope.GlobalScope;
import com.android.build.gradle.internal.scope.InternalArtifactType;
import com.android.build.gradle.internal.scope.VariantScope;
import com.android.build.gradle.internal.tasks.BundleLibraryClasses;
import com.android.build.gradle.internal.tasks.BundleLibraryJavaRes;
import com.android.build.gradle.internal.tasks.LibraryDexingTask;
import com.android.build.gradle.internal.tasks.LibraryJniLibsTask;
import com.android.build.gradle.internal.tasks.MergeConsumerProguardFilesTask;
import com.android.build.gradle.internal.tasks.MergeGeneratedProguardFilesCreationAction;
import com.android.build.gradle.internal.tasks.PackageRenderscriptTask;
import com.android.build.gradle.internal.tasks.StripDebugSymbolsTask;
import com.android.build.gradle.internal.tasks.factory.TaskFactoryUtils;
import com.android.build.gradle.internal.tasks.factory.TaskProviderCallback;
import com.android.build.gradle.internal.transforms.LibraryAarJarsTransform;
import com.android.build.gradle.internal.variant.VariantFactory;
import com.android.build.gradle.internal.variant.VariantHelper;
import com.android.build.gradle.options.BooleanOption;
import com.android.build.gradle.options.ProjectOptions;
import com.android.build.gradle.tasks.BuildArtifactReportTask;
import com.android.build.gradle.tasks.BundleAar;
import com.android.build.gradle.tasks.ExtractAnnotations;
import com.android.build.gradle.tasks.ExtractDeepLinksTask;
import com.android.build.gradle.tasks.MergeResources;
import com.android.build.gradle.tasks.MergeSourceSetFolders;
import com.android.build.gradle.tasks.VerifyLibraryResourcesTask;
import com.android.build.gradle.tasks.ZipMergingTask;
import com.android.builder.errors.EvalIssueException;
import com.android.builder.errors.EvalIssueReporter.Type;
import com.android.builder.profile.Recorder;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Supplier;
import org.gradle.api.Project;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry;

/** TaskManager for creating tasks in an Android library project. */
public class LibraryTaskManager extends TaskManager {

    public LibraryTaskManager(
            @NonNull GlobalScope globalScope,
            @NonNull Project project,
            @NonNull ProjectOptions projectOptions,
            @NonNull DataBindingBuilder dataBindingBuilder,
            @NonNull AndroidConfig extension,
            @NonNull VariantFactory variantFactory,
            @NonNull ToolingModelBuilderRegistry toolingRegistry,
            @NonNull Recorder recorder) {
        super(
                globalScope,
                project,
                projectOptions,
                dataBindingBuilder,
                extension,
                variantFactory,
                toolingRegistry,
                recorder);
    }

    @Override
    public void createTasksForVariantScope(@NonNull final VariantScope variantScope) {
        final GradleVariantConfiguration variantConfig = variantScope.getVariantConfiguration();

        GlobalScope globalScope = variantScope.getGlobalScope();

        createAnchorTasks(variantScope);

        taskFactory.register(new ExtractDeepLinksTask.CreationAction(variantScope));

        // Create all current streams (dependencies mostly at this point)
        createDependencyStreams(variantScope);

        createCheckManifestTask(variantScope);

        taskFactory.register(
                new BuildArtifactReportTask.BuildArtifactReportCreationAction(variantScope));

        createGenerateResValuesTask(variantScope);

        createMergeLibManifestsTask(variantScope);

        createRenderscriptTask(variantScope);

        createMergeResourcesTasks(variantScope);

        createShaderTask(variantScope);

        // Add tasks to merge the assets folders
        createMergeAssetsTask(variantScope);
        createLibraryAssetsTask(variantScope);

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

        // Add a task to generate resource source files, directing the location
        // of the r.txt file to be directly in the bundle.
        createProcessResTask(
                variantScope,
                variantScope.getSymbolTableFile(),
                null,
                // Switch to package where possible so we stop merging resources in
                // libraries
                MergeType.PACKAGE,
                globalScope.getProjectBaseName());

        // Only verify resources if in Release and not namespaced.
        if (!variantScope.getVariantConfiguration().getBuildType().isDebuggable()
                && !variantScope.getGlobalScope().getExtension().getAaptOptions().getNamespaced()) {
            createVerifyLibraryResTask(variantScope);
        }
        registerLibraryRClassTransformStream(variantScope);

        // process java resources only, the merge is setup after
        // the task to generate intermediate jars for project to project publishing.
        createProcessJavaResTask(variantScope);

        createAidlTask(variantScope);

        // Add data binding tasks if enabled
        createDataBindingTasksIfNecessary(variantScope, MergeType.PACKAGE);

        // Add a compile task
        TaskProvider<? extends JavaCompile> javacTask = createJavacTask(variantScope);
        addJavacClassesStream(variantScope);
        TaskManager.setJavaCompilerTask(javacTask, variantScope);

        taskFactory.register(new MergeGeneratedProguardFilesCreationAction(variantScope));

        // External native build
        createExternalNativeBuildJsonGenerators(variantScope);
        createExternalNativeBuildTasks(variantScope);

        createMergeJniLibFoldersTasks(variantScope);

        taskFactory.register(new StripDebugSymbolsTask.CreationAction(variantScope));

        taskFactory.register(new PackageRenderscriptTask.CreationAction(variantScope));

        // merge consumer proguard files from different build types and flavors
        taskFactory.register(new MergeConsumerProguardFilesTask.CreationAction(variantScope));

        // Some versions of retrolambda remove the actions from the extract annotations task.
        // TODO: remove this hack once tests are moved to a version that doesn't do this
        // b/37564303
        if (projectOptions.get(BooleanOption.ENABLE_EXTRACT_ANNOTATIONS)) {
            taskFactory.register(new ExtractAnnotations.CreationAction(extension, variantScope));
        }

        final boolean instrumented = variantConfig.getBuildType().isTestCoverageEnabled();

        TransformManager transformManager = variantScope.getTransformManager();

        // ----- Code Coverage first -----
        if (instrumented) {
            createJacocoTask(variantScope);
        }

        // ----- External Transforms -----
        // apply all the external transforms.
        List<Transform> customTransforms = extension.getTransforms();
        List<List<Object>> customTransformsDependencies = extension.getTransformsDependencies();

        for (int i = 0, count = customTransforms.size(); i < count; i++) {
            Transform transform = customTransforms.get(i);

            // Check the transform only applies to supported scopes for libraries:
            // We cannot transform scopes that are not packaged in the library
            // itself.
            Sets.SetView<? super Scope> difference =
                    Sets.difference(transform.getScopes(), TransformManager.PROJECT_ONLY);
            if (!difference.isEmpty()) {
                String scopes = difference.toString();
                globalScope
                        .getErrorHandler()
                        .reportError(
                                Type.GENERIC,
                                new EvalIssueException(
                                        String.format(
                                                "Transforms with scopes '%s' cannot be applied to library projects.",
                                                scopes)));
            }

            List<Object> deps = customTransformsDependencies.get(i);
            transformManager.addTransform(
                    taskFactory,
                    variantScope,
                    transform,
                    null,
                    task -> {
                        if (!deps.isEmpty()) {
                            task.dependsOn(deps);
                        }
                    },
                    taskProvider -> {
                        // if the task is a no-op then we make assemble task
                        // depend on it.
                        if (transform.getScopes().isEmpty()) {
                            TaskFactoryUtils.dependsOn(
                                    variantScope.getTaskContainer().getAssembleTask(),
                                    taskProvider);
                        }
                    });
        }

        // Create jar with library classes used for publishing to runtime elements.
        taskFactory.register(
                new BundleLibraryClasses.CreationAction(
                        variantScope,
                        AndroidArtifacts.PublishedConfigType.RUNTIME_ELEMENTS,
                        excludeDataBindingClassesIfNecessary(variantScope)));
        taskFactory.register(new BundleLibraryJavaRes.CreationAction(variantScope));

        taskFactory.register(new LibraryDexingTask.CreationAction(variantScope));

        // Create a jar with both classes and java resources.  This artifact is not
        // used by the Android application plugin and the task usually don't need to
        // be executed.  The artifact is useful for other Gradle users who needs the
        // 'jar' artifact as API dependency.
        taskFactory.register(new ZipMergingTask.CreationAction(variantScope));

        // now add a task that will take all the native libs and package
        // them into an intermediary folder. This processes only the PROJECT
        // scope.
        taskFactory.register(
                new LibraryJniLibsTask.ProjectOnlyCreationAction(
                        variantScope, InternalArtifactType.LIBRARY_JNI));

        // Now go back to fill the pipeline with transforms used when
        // publishing the AAR

        // first merge the java resources.
        createMergeJavaResTask(variantScope);

        // ----- Minify next -----
        maybeCreateJavaCodeShrinkerTransform(variantScope);
        maybeCreateResourcesShrinkerTransform(variantScope);

        // now add a transform that will take all the class/res and package them
        // into the main and secondary jar files that goes in the AAR.
        // This transform technically does not use its transform output, but that's
        // ok. We use the transform mechanism to get incremental data from
        // the streams.
        // This is used for building the AAR.

        File classesJar = variantScope.getAarClassesJar();
        File libsDirectory = variantScope.getAarLibsDirectory();
        BuildArtifactsHolder artifacts = variantScope.getArtifacts();

        LibraryAarJarsTransform transform =
                new LibraryAarJarsTransform(
                        classesJar,
                        libsDirectory,
                        artifacts.hasFinalProduct(InternalArtifactType.ANNOTATIONS_TYPEDEF_FILE)
                                ? artifacts.getFinalProduct(
                                        InternalArtifactType.ANNOTATIONS_TYPEDEF_FILE)
                                : null,
                        variantConfig::getPackageFromManifest,
                        extension.getPackageBuildConfig());

        transform.setExcludeListProvider(excludeDataBindingClassesIfNecessary(variantScope));

        transformManager.addTransform(
                taskFactory,
                variantScope,
                transform,
                taskName -> {
                    artifacts.appendArtifact(
                            InternalArtifactType.AAR_MAIN_JAR,
                            ImmutableList.of(classesJar),
                            taskName);
                    artifacts.appendArtifact(
                            InternalArtifactType.AAR_LIBS_DIRECTORY,
                            ImmutableList.of(libsDirectory),
                            taskName);
                },
                null,
                null);

        // now add a task that will take all the native libs and package
        // them into the libs folder of the bundle. This processes both the PROJECT
        // and the LOCAL_PROJECT scopes
        taskFactory.register(
                new LibraryJniLibsTask.ProjectAndLocalJarsCreationAction(
                        variantScope, InternalArtifactType.LIBRARY_AND_LOCAL_JARS_JNI));

        createLintTasks(variantScope);
        createBundleTask(variantScope);
    }

    private void registerLibraryRClassTransformStream(@NonNull VariantScope variantScope) {
        InternalArtifactType rClassJar;

        if (globalScope.getExtension().getAaptOptions().getNamespaced()) {
            rClassJar = InternalArtifactType.COMPILE_ONLY_NAMESPACED_R_CLASS_JAR;
        } else {
            rClassJar = InternalArtifactType.COMPILE_ONLY_NOT_NAMESPACED_R_CLASS_JAR;
        }
        QualifiedContent.ScopeType scopeType;
        if (variantScope.getCodeShrinker() != null) {
            // Add the R class classes as production classes. They are then removed by the library
            // jar transform.
            // TODO(b/115974418): Can we stop adding the compilation-only R class as a local classes?
            scopeType = Scope.PROJECT;
        } else {
            scopeType = Scope.PROVIDED_ONLY;
        }

        FileCollection compileRClass =
                project.files(variantScope.getArtifacts().getFinalProduct(rClassJar));
        variantScope
                .getTransformManager()
                .addStream(
                        OriginalStream.builder(project, "compile-only-r-class")
                                .addContentTypes(TransformManager.CONTENT_CLASS)
                                .addScope(scopeType)
                                .setFileCollection(compileRClass)
                                .build());
    }

    private void createBundleTask(@NonNull VariantScope variantScope) {
        TaskProvider<BundleAar> bundle =
                taskFactory.register(new BundleAar.CreationAction(extension, variantScope));

        TaskFactoryUtils.dependsOn(variantScope.getTaskContainer().getAssembleTask(), bundle);

        // if the variant is the default published, then publish the aar
        // FIXME: only generate the tasks if this is the default published variant?
        if (extension
                .getDefaultPublishConfig()
                .equals(variantScope.getVariantConfiguration().getFullName())) {
            VariantHelper.setupArchivesConfig(
                    project, variantScope.getVariantDependencies().getRuntimeClasspath());

            // add the artifact that will be published.
            // it must be default so that it can be found by other library modules during
            // publishing to a maven repo. Adding it to "archives" only allows the current
            // module to be published by not to be found by consumer who are themselves published
            // (leading to their pom not containing dependencies).
            project.getArtifacts().add("default", bundle);
        }
    }

    @Override
    protected void createDependencyStreams(@NonNull VariantScope variantScope) {
        super.createDependencyStreams(variantScope);

        // add the same jars twice in the same stream as the EXTERNAL_LIB in the task manager
        // so that filtering of duplicates in proguard can work.
        variantScope
                .getTransformManager()
                .addStream(
                        OriginalStream.builder(project, "local-deps-classes")
                                .addContentTypes(TransformManager.CONTENT_CLASS)
                                .addScope(InternalScope.LOCAL_DEPS)
                                .setFileCollection(variantScope.getLocalPackagedJars())
                                .build());
    }

    private static class MergeResourceCallback implements TaskProviderCallback<MergeResources> {
        private final VariantScope variantScope;

        private MergeResourceCallback(VariantScope variantScope) {
            this.variantScope = variantScope;
        }

        @Override
        public void handleProvider(@NonNull TaskProvider<? extends MergeResources> taskProvider) {

            variantScope
                    .getArtifacts()
                    .producesFile(
                            InternalArtifactType.PUBLIC_RES,
                            BuildArtifactsHolder.OperationType.INITIAL,
                            taskProvider,
                            MergeResources::getPublicFile,
                            FN_PUBLIC_TXT);

        }
    }

    private void createMergeResourcesTasks(@NonNull VariantScope variantScope) {
        ImmutableSet<MergeResources.Flag> flags;
        if (variantScope.getGlobalScope().getExtension().getAaptOptions().getNamespaced()) {
            flags =
                    Sets.immutableEnumSet(
                            MergeResources.Flag.REMOVE_RESOURCE_NAMESPACES,
                            MergeResources.Flag.PROCESS_VECTOR_DRAWABLES);
        } else {
            flags = Sets.immutableEnumSet(MergeResources.Flag.PROCESS_VECTOR_DRAWABLES);
        }

        MergeResourceCallback callback = new MergeResourceCallback(variantScope);

        // Create a merge task to only merge the resources from this library and not
        // the dependencies. This is what gets packaged in the aar.
        basicCreateMergeResourcesTask(
                variantScope,
                MergeType.PACKAGE,
                variantScope.getIntermediateDir(InternalArtifactType.PACKAGED_RES),
                false,
                false,
                false,
                flags,
                callback);


        // This task merges all the resources, including the dependencies of this library.
        // This should be unused, except that external libraries might consume it.
        createMergeResourcesTask(variantScope, false /*processResources*/, ImmutableSet.of());
    }

    @Override
    protected void postJavacCreation(@NonNull VariantScope scope) {
        // create an anchor collection for usage inside the same module (unit tests basically)
        ConfigurableFileCollection files =
                scope.getGlobalScope()
                        .getProject()
                        .files(
                                scope.getArtifacts().getFinalProduct(JAVAC),
                                scope.getVariantData().getAllPreJavacGeneratedBytecode(),
                                scope.getVariantData().getAllPostJavacGeneratedBytecode());
        scope.getArtifacts().appendArtifact(AnchorOutputType.ALL_CLASSES, files);

        // Create jar used for publishing to API elements (for other projects to compile against).
        taskFactory.register(
                new BundleLibraryClasses.CreationAction(
                        scope,
                        AndroidArtifacts.PublishedConfigType.API_ELEMENTS,
                        excludeDataBindingClassesIfNecessary(scope)));
    }

    @NonNull
    private Supplier<List<String>> excludeDataBindingClassesIfNecessary(
            @NonNull VariantScope variantScope) {
        if (!extension.getDataBinding().isEnabled()) {
            return Collections::emptyList;
        }

        return () -> {
            File excludeFile =
                    variantScope.getVariantData().getType().isExportDataBindingClassList()
                            ? variantScope.getGeneratedClassListOutputFileForDataBinding()
                            : null;
            File dependencyArtifactsDir =
                    variantScope
                            .getArtifacts()
                            .getFinalProduct(InternalArtifactType.DATA_BINDING_DEPENDENCY_ARTIFACTS)
                            .get()
                            .getAsFile();
            return dataBindingBuilder.getJarExcludeList(
                    variantScope.getVariantData().getLayoutXmlProcessor(),
                    excludeFile,
                    dependencyArtifactsDir);
        };
    }

    public void createLibraryAssetsTask(@NonNull VariantScope scope) {
        taskFactory.register(new MergeSourceSetFolders.LibraryAssetCreationAction(scope));
    }

    @NonNull
    @Override
    protected Set<ScopeType> getJavaResMergingScopes(
            @NonNull VariantScope variantScope, @NonNull QualifiedContent.ContentType contentType) {
        Preconditions.checkArgument(
                contentType == RESOURCES || contentType == NATIVE_LIBS,
                "contentType must be RESOURCES or NATIVE_LIBS");
        if (variantScope.getTestedVariantData() != null) {
            if (contentType == RESOURCES) {
                return TransformManager.SCOPE_FULL_PROJECT_WITH_LOCAL_JARS;
            }
            // contentType is NATIVE_LIBS
            return TransformManager.SCOPE_FULL_PROJECT;
        }
        if (contentType == RESOURCES) {
            return TransformManager.SCOPE_FULL_LIBRARY_WITH_LOCAL_JARS;
        }
        // contentType is NATIVE_LIBS
        return TransformManager.PROJECT_ONLY;
    }

    @Override
    protected boolean isLibrary() {
        return true;
    }

    public void createVerifyLibraryResTask(@NonNull VariantScope scope) {
        TaskProvider<VerifyLibraryResourcesTask> verifyLibraryResources =
                taskFactory.register(new VerifyLibraryResourcesTask.CreationAction(scope));

        TaskFactoryUtils.dependsOn(
                scope.getTaskContainer().getAssembleTask(), verifyLibraryResources);
    }
}
