/*
 * 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.internal.dsl;

import com.android.annotations.NonNull;
import com.android.annotations.Nullable;
import com.android.build.gradle.api.JavaCompileOptions;
import com.android.build.gradle.internal.errors.DeprecationReporter;
import com.android.build.gradle.internal.scope.CodeShrinker;
import com.android.builder.core.BuilderConstants;
import com.android.builder.core.DefaultBuildType;
import com.android.builder.errors.EvalIssueReporter;
import com.android.builder.errors.EvalIssueReporter.Type;
import com.android.builder.internal.ClassFieldImpl;
import com.android.builder.model.BaseConfig;
import com.android.builder.model.ClassField;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.io.Serializable;
import java.util.List;
import java.util.function.Supplier;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.Project;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Internal;

/** DSL object to configure build types. */
@SuppressWarnings({"unused", "WeakerAccess", "UnusedReturnValue", "Convert2Lambda"})
public class BuildType extends DefaultBuildType implements CoreBuildType, Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * Whether the current thread should check that the both the old and new way of configuring
     * bytecode postProcessing are not used at the same time.
     *
     * <p>The checks are disabled during {@link #initWith(com.android.builder.model.BuildType)}.
     */
    private static ThreadLocal<Boolean> dslChecksEnabled =
            ThreadLocal.withInitial(
                    new Supplier<Boolean>() {
                        @Override
                        public Boolean get() {
                            return true;
                        }
                    });

    /**
     * Describes how code postProcessing is configured. We don't allow mixing the old and new DSLs.
     */
    public enum PostProcessingConfiguration {
        POSTPROCESSING_BLOCK,
        OLD_DSL,
    }

    @NonNull private final Project project;
    @NonNull private final NdkOptions ndkConfig;
    @NonNull private final ExternalNativeBuildOptions externalNativeBuildOptions;
    @NonNull
    private final com.android.build.gradle.internal.dsl.JavaCompileOptions javaCompileOptions;
    @NonNull private final ShaderOptions shaderOptions;
    @NonNull private final EvalIssueReporter issueReporter;
    @NonNull private final DeprecationReporter deprecationReporter;
    @NonNull private final PostProcessingBlock postProcessingBlock;

    @Nullable private PostProcessingConfiguration postProcessingConfiguration;
    @Nullable private String postProcessingDslMethodUsed;

    private boolean shrinkResources = false;
    private Boolean useProguard = false;
    private Boolean crunchPngs;
    private boolean isCrunchPngsDefault = true;
    private final Property<Boolean> isDefault;

    @Inject
    public BuildType(
            @NonNull String name,
            @NonNull Project project,
            @NonNull ObjectFactory objectFactory,
            @NonNull EvalIssueReporter issueReporter,
            @NonNull DeprecationReporter deprecationReporter) {
        super(name);
        this.project = project;
        this.issueReporter = issueReporter;
        this.deprecationReporter = deprecationReporter;

        javaCompileOptions =
                objectFactory.newInstance(
                        com.android.build.gradle.internal.dsl.JavaCompileOptions.class,
                        objectFactory);
        shaderOptions = objectFactory.newInstance(ShaderOptions.class);
        ndkConfig = objectFactory.newInstance(NdkOptions.class);
        externalNativeBuildOptions =
                objectFactory.newInstance(ExternalNativeBuildOptions.class, objectFactory);
        postProcessingBlock = objectFactory.newInstance(PostProcessingBlock.class, project);
        isDefault = objectFactory.property(Boolean.class).convention(false);
    }

    @VisibleForTesting
    BuildType(
            @NonNull String name,
            @NonNull Project project,
            @NonNull EvalIssueReporter issueReporter,
            @NonNull DeprecationReporter deprecationReporter) {

        super(name);
        this.project = project;
        this.issueReporter = issueReporter;
        this.deprecationReporter = deprecationReporter;
        javaCompileOptions = new com.android.build.gradle.internal.dsl.JavaCompileOptions();
        shaderOptions = new ShaderOptions();
        ndkConfig = new NdkOptions();
        externalNativeBuildOptions = new ExternalNativeBuildOptions();
        postProcessingBlock = new PostProcessingBlock(project);
        isDefault = project.getObjects().property(Boolean.class).convention(false);
    }

    private ImmutableList<String> matchingFallbacks;

    public void setMatchingFallbacks(String... fallbacks) {
        this.matchingFallbacks = ImmutableList.copyOf(fallbacks);
    }

    public void setMatchingFallbacks(List<String> fallbacks) {
        this.matchingFallbacks = ImmutableList.copyOf(fallbacks);
    }

    public void setMatchingFallbacks(String fallback) {
        this.matchingFallbacks = ImmutableList.of(fallback);
    }

    /**
     * Specifies a sorted list of build types that the plugin should try to use when a direct
     * variant match with a local module dependency is not possible.
     *
     * <p>Android plugin 3.0.0 and higher try to match each variant of your module with the same one
     * from its dependencies. For example, when you build a "freeDebug" version of your app, the
     * plugin tries to match it with "freeDebug" versions of the local library modules the app
     * depends on.
     *
     * <p>However, there may be situations in which <b>your app includes build types that a
     * dependency does not</b>. For example, consider if your app includes a "stage" build type, but
     * a dependency includes only a "debug" and "release" build type. When the plugin tries to build
     * the "stage" version of your app, it won't know which version of the dependency to use, and
     * you'll see an error message similar to the following:
     *
     * <pre>
     * Error:Failed to resolve: Could not resolve project :mylibrary.
     * Required by:
     *     project :app
     * </pre>
     *
     * <p>In this situation, you can use <code>matchingFallbacks</code> to specify alternative
     * matches for the app's "stage" build type, as shown below:
     *
     * <pre>
     * // In the app's build.gradle file.
     * android {
     *     buildTypes {
     *         release {
     *             // Because the dependency already includes a "release" build type,
     *             // you don't need to provide a list of fallbacks here.
     *         }
     *         stage {
     *             // Specifies a sorted list of fallback build types that the
     *             // plugin should try to use when a dependency does not include a
     *             // "stage" build type. You may specify as many fallbacks as you
     *             // like, and the plugin selects the first build type that's
     *             // available in the dependency.
     *             matchingFallbacks = ['debug', 'qa', 'release']
     *         }
     *     }
     * }
     * </pre>
     *
     * <p>Note that there is no issue when a library dependency includes a build type that your app
     * does not. That's because the plugin simply never requests that build type from the
     * dependency.
     *
     * @return the names of product flavors to use, in descending priority order
     */
    public List<String> getMatchingFallbacks() {
        if (matchingFallbacks == null) {
            return ImmutableList.of();
        }
        return matchingFallbacks;
    }

    @Override
    @NonNull
    public CoreNdkOptions getNdkConfig() {
        return ndkConfig;
    }

    @Override
    @NonNull
    public ExternalNativeBuildOptions getExternalNativeBuildOptions() {
        return externalNativeBuildOptions;
    }

    /** Options for configuration Java compilation. */
    @Override
    @NonNull
    public JavaCompileOptions getJavaCompileOptions() {
        return javaCompileOptions;
    }

    @NonNull
    @Override
    public CoreShaderOptions getShaders() {
        return shaderOptions;
    }

    /**
     * Initialize the DSL object with the debug signingConfig. Not meant to be used from the build
     * scripts.
     */
    public void init(SigningConfig debugSigningConfig) {
        init();
        if (BuilderConstants.DEBUG.equals(getName())) {
            assert debugSigningConfig != null;
            setSigningConfig(debugSigningConfig);
        }
    }

    /**
     * Initialize the DSL object without the signingConfig. Not meant to be used from the build
     * scripts.
     */
    public void init() {
        if (BuilderConstants.DEBUG.equals(getName())) {
            setDebuggable(true);
            setEmbedMicroApp(false);
            isCrunchPngsDefault = false;
        }
    }

    /** The signing configuration. */
    @Override
    @Nullable
    public SigningConfig getSigningConfig() {
        return (SigningConfig) super.getSigningConfig();
    }


    /** {@inheritDoc} */
    @SuppressWarnings("UnnecessaryInheritDoc")
    @Override
    public Property<Boolean> getIsDefault() {
        return isDefault;
    }

    @Override
    protected void _initWith(@NonNull BaseConfig that) {
        super._initWith(that);
        BuildType thatBuildType = (BuildType) that;
        ndkConfig._initWith(thatBuildType.getNdkConfig());
        javaCompileOptions.getAnnotationProcessorOptions()._initWith(
                thatBuildType.getJavaCompileOptions().getAnnotationProcessorOptions());
        shrinkResources = thatBuildType.isShrinkResources();
        shaderOptions._initWith(thatBuildType.getShaders());
        externalNativeBuildOptions._initWith(thatBuildType.getExternalNativeBuildOptions());
        useProguard = thatBuildType.isUseProguard();
        postProcessingBlock.initWith(((BuildType) that).getPostprocessing());
        crunchPngs = thatBuildType.isCrunchPngs();
        //noinspection deprecation Must still be copied.
        isCrunchPngsDefault = thatBuildType.isCrunchPngsDefault();
        matchingFallbacks = ImmutableList.copyOf(thatBuildType.getMatchingFallbacks());
        // we don't want to dynamically link these values. We just want to copy the current value.
        isDefault.set(thatBuildType.getIsDefault().get());
    }

    /** Override as DSL objects have no reason to be compared for equality. */
    @Override
    public int hashCode() {
        return System.identityHashCode(this);
    }

    /** Override as DSL objects have no reason to be compared for equality. */
    @Override
    public boolean equals(Object o) {
        return this == o;
    }

    // -- DSL Methods. TODO remove once the instantiator does what I expect it to do.

    /**
     * Adds a new field to the generated BuildConfig class.
     *
     * <p>The field is generated as: {@code <type> <name> = <value>;}
     *
     * <p>This means each of these must have valid Java content. If the type is a String, then the
     * value should include quotes.
     *
     * @param type the type of the field
     * @param name the name of the field
     * @param value the value of the field
     */
    public void buildConfigField(
            @NonNull String type,
            @NonNull String name,
            @NonNull String value) {
        ClassField alreadyPresent = getBuildConfigFields().get(name);
        if (alreadyPresent != null) {
            String message =
                    String.format(
                            "BuildType(%s): buildConfigField '%s' value is being replaced: %s -> %s",
                            getName(), name, alreadyPresent.getValue(), value);
            issueReporter.reportWarning(Type.GENERIC, message);
        }
        addBuildConfigField(new ClassFieldImpl(type, name, value));
    }

    /**
     * Adds a new generated resource.
     *
     * <p>This is equivalent to specifying a resource in res/values.
     *
     * <p>See <a href="http://developer.android.com/guide/topics/resources/available-resources.html">Resource Types</a>.
     *
     * @param type the type of the resource
     * @param name the name of the resource
     * @param value the value of the resource
     */
    public void resValue(
            @NonNull String type,
            @NonNull String name,
            @NonNull String value) {
        ClassField alreadyPresent = getResValues().get(name);
        if (alreadyPresent != null) {
            String message =
                    String.format(
                            "BuildType(%s): resValue '%s' value is being replaced: %s -> %s",
                            getName(), name, alreadyPresent.getValue(), value);
            issueReporter.reportWarning(Type.GENERIC, message);
        }
        addResValue(new ClassFieldImpl(type, name, value));
    }

    /**
     * Adds a new ProGuard configuration file.
     *
     * <p><code>proguardFile getDefaultProguardFile('proguard-android.txt')</code></p>
     *
     * <p>There are 2 default rules files
     * <ul>
     *     <li>proguard-android.txt
     *     <li>proguard-android-optimize.txt
     * </ul>
     * <p>They are located in the SDK. Using <code>getDefaultProguardFile(String filename)</code> will return the
     * full path to the files. They are identical except for enabling optimizations.
     */
    @NonNull
    public BuildType proguardFile(@NonNull Object proguardFile) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "proguardFile");
        getProguardFiles().add(project.file(proguardFile));
        return this;
    }

    /**
     * Adds new ProGuard configuration files.
     *
     * <p>There are 2 default rules files
     * <ul>
     *     <li>proguard-android.txt
     *     <li>proguard-android-optimize.txt
     * </ul>
     * <p>They are located in the SDK. Using <code>getDefaultProguardFile(String filename)</code> will return the
     * full path to the files. They are identical except for enabling optimizations.
     */
    @NonNull
    public BuildType proguardFiles(@NonNull Object... files) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "proguardFiles");
        for (Object file : files) {
            proguardFile(file);
        }
        return this;
    }

    /**
     * Sets the ProGuard configuration files.
     *
     * <p>There are 2 default rules files
     * <ul>
     *     <li>proguard-android.txt
     *     <li>proguard-android-optimize.txt
     * </ul>
     * <p>They are located in the SDK. Using <code>getDefaultProguardFile(String filename)</code> will return the
     * full path to the files. They are identical except for enabling optimizations.
     */
    @NonNull
    public BuildType setProguardFiles(@NonNull Iterable<?> proguardFileIterable) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "setProguardFiles");
        getProguardFiles().clear();
        proguardFiles(Iterables.toArray(proguardFileIterable, Object.class));
        return this;
    }

    /**
     * Adds a proguard rule file to be used when processing test code.
     *
     * <p>Test code needs to be processed to apply the same obfuscation as was done to main code.
     */
    @NonNull
    public BuildType testProguardFile(@NonNull Object proguardFile) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "testProguardFile");
        getTestProguardFiles().add(project.file(proguardFile));
        return this;
    }

    /**
     * Adds proguard rule files to be used when processing test code.
     *
     * <p>Test code needs to be processed to apply the same obfuscation as was done to main code.
     */
    @NonNull
    public BuildType testProguardFiles(@NonNull Object... proguardFiles) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "testProguardFiles");
        for (Object proguardFile : proguardFiles) {
            testProguardFile(proguardFile);
        }
        return this;
    }

    /**
     * Specifies proguard rule files to be used when processing test code.
     *
     * <p>Test code needs to be processed to apply the same obfuscation as was done to main code.
     */
    @NonNull
    public BuildType setTestProguardFiles(@NonNull Iterable<?> files) {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.OLD_DSL, "setTestProguardFiles");
        getTestProguardFiles().clear();
        testProguardFiles(Iterables.toArray(files, Object.class));
        return this;
    }

    /**
     * Adds a proguard rule file to be included in the published AAR.
     *
     * <p>This proguard rule file will then be used by any application project that consume the AAR
     * (if proguard is enabled).
     *
     * <p>This allows AAR to specify shrinking or obfuscation exclude rules.
     *
     * <p>This is only valid for Library project. This is ignored in Application project.
     */
    @NonNull
    public BuildType consumerProguardFile(@NonNull Object proguardFile) {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.OLD_DSL, "consumerProguardFile");
        getConsumerProguardFiles().add(project.file(proguardFile));
        return this;
    }

    /**
     * Adds proguard rule files to be included in the published AAR.
     *
     * <p>This proguard rule file will then be used by any application project that consume the AAR
     * (if proguard is enabled).
     *
     * <p>This allows AAR to specify shrinking or obfuscation exclude rules.
     *
     * <p>This is only valid for Library project. This is ignored in Application project.
     */
    @NonNull
    public BuildType consumerProguardFiles(@NonNull Object... proguardFiles) {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.OLD_DSL, "consumerProguardFiles");
        for (Object proguardFile : proguardFiles) {
            consumerProguardFile(proguardFile);
        }

        return this;
    }

    /**
     * Specifies a proguard rule file to be included in the published AAR.
     *
     * <p>This proguard rule file will then be used by any application project that consume the AAR
     * (if proguard is enabled).
     *
     * <p>This allows AAR to specify shrinking or obfuscation exclude rules.
     *
     * <p>This is only valid for Library project. This is ignored in Application project.
     */
    @NonNull
    public BuildType setConsumerProguardFiles(@NonNull Iterable<?> proguardFileIterable) {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.OLD_DSL, "setConsumerProguardFiles");
        getConsumerProguardFiles().clear();
        consumerProguardFiles(Iterables.toArray(proguardFileIterable, Object.class));
        return this;
    }


    public void ndk(@NonNull Action<NdkOptions> action) {
        action.execute(ndkConfig);
    }

    /**
     * Configure native build options.
     */
    public ExternalNativeBuildOptions externalNativeBuild(@NonNull Action<ExternalNativeBuildOptions> action) {
        action.execute(externalNativeBuildOptions);
        return externalNativeBuildOptions;
    }

    /**
     * Configure shader compiler options for this build type.
     */
    public void shaders(@NonNull Action<ShaderOptions> action) {
        action.execute(shaderOptions);
    }

    @NonNull
    @Override
    public com.android.builder.model.BuildType setMinifyEnabled(boolean enabled) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "setMinifyEnabled");
        return super.setMinifyEnabled(enabled);
    }

    /**
     * Whether removal of unused java code is enabled.
     *
     * <p>Default is false.
     */
    @Override
    public boolean isMinifyEnabled() {
        // Try to return a sensible value for the model and third party plugins inspecting the DSL.
        if (postProcessingConfiguration != PostProcessingConfiguration.POSTPROCESSING_BLOCK) {
            return super.isMinifyEnabled();
        } else {
            return postProcessingBlock.isRemoveUnusedCode()
                    || postProcessingBlock.isObfuscate()
                    || postProcessingBlock.isOptimizeCode();
        }
    }

    /**
     * Whether shrinking of unused resources is enabled.
     *
     * Default is false;
     */
    @Override
    public boolean isShrinkResources() {
        // Try to return a sensible value for the model and third party plugins inspecting the DSL.
        if (postProcessingConfiguration != PostProcessingConfiguration.POSTPROCESSING_BLOCK) {
            return shrinkResources;
        } else {
            return postProcessingBlock.isRemoveUnusedResources();
        }
    }

    public void setShrinkResources(boolean shrinkResources) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "setShrinkResources");
        this.shrinkResources = shrinkResources;
    }

    /**
     * Specifies whether to always use ProGuard for code and resource shrinking.
     *
     * <p>By default, when you enable code shrinking by setting <a
     * href="com.android.build.gradle.internal.dsl.BuildType.html#com.android.build.gradle.internal.dsl.BuildType:minifyEnabled">
     * <code>minifyEnabled</code></a> to <code>true</code>, the Android plugin uses R8. If you set
     * this property to <code>true</code>, the Android plugin uses ProGuard.
     *
     * <p>To learn more, read <a
     * href="https://developer.android.com/studio/build/shrink-code.html">Shrink, obfuscate, and
     * optimize your app</a>.
     */
    @Override
    public Boolean isUseProguard() {
        // Try to return a sensible value for the model and third party plugins inspecting the DSL.
        if (postProcessingConfiguration != PostProcessingConfiguration.POSTPROCESSING_BLOCK) {
            return useProguard;
        } else {
            return postProcessingBlock.getCodeShrinkerEnum() == CodeShrinker.PROGUARD;
        }
    }

    public void setUseProguard(boolean useProguard) {
        checkPostProcessingConfiguration(PostProcessingConfiguration.OLD_DSL, "setUseProguard");
        if (dslChecksEnabled.get()) {
            deprecationReporter.reportObsoleteUsage(
                    "useProguard", DeprecationReporter.DeprecationTarget.DSL_USE_PROGUARD);
        }
    }

    /** {@inheritDoc} */
    @Override
    public Boolean isCrunchPngs() {
        return crunchPngs;
    }

    public void setCrunchPngs(Boolean crunchPngs) {
        this.crunchPngs = crunchPngs;
    }

    /*
     * (Non javadoc): Whether png crunching should be enabled if not explicitly overridden.
     *
     * Can be removed once the AaptOptions crunch method is removed.
     */
    @Override
    @Deprecated
    public boolean isCrunchPngsDefault() {
        return isCrunchPngsDefault;
    }

    /** This DSL is incubating and subject to change. */
    @Incubating
    @Internal
    @NonNull
    public PostProcessingBlock getPostprocessing() {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.POSTPROCESSING_BLOCK, "getPostProcessing");
        return postProcessingBlock;
    }

    /** This DSL is incubating and subject to change. */
    @Incubating
    @Internal
    public void postprocessing(@NonNull Action<PostProcessingBlock> action) {
        checkPostProcessingConfiguration(
                PostProcessingConfiguration.POSTPROCESSING_BLOCK, "postProcessing");
        action.execute(postProcessingBlock);
    }

    /** Describes how postProcessing was configured. Not to be used from the DSL. */
    @NonNull
    public PostProcessingConfiguration getPostProcessingConfiguration() {
        // If the user didn't configure anything, stick to the old DSL.
        return postProcessingConfiguration != null
                ? postProcessingConfiguration
                : PostProcessingConfiguration.OLD_DSL;
    }

    /**
     * Checks that the user is consistently using either the new or old DSL for configuring bytecode
     * postProcessing.
     */
    private void checkPostProcessingConfiguration(
            @NonNull PostProcessingConfiguration used, @NonNull String methodName) {
        if (!dslChecksEnabled.get()) {
            return;
        }

        if (this.postProcessingConfiguration == null) {
            this.postProcessingConfiguration = used;
            this.postProcessingDslMethodUsed = methodName;
        } else if (this.postProcessingConfiguration != used) {
            assert postProcessingDslMethodUsed != null;
            String message;
            switch (used) {
                case POSTPROCESSING_BLOCK:
                    // TODO: URL with more details.
                    message =
                            String.format(
                                    "The `postProcessing` block cannot be used with together with the `%s` method.",
                                    postProcessingDslMethodUsed);
                    break;
                case OLD_DSL:
                    // TODO: URL with more details.
                    message =
                            String.format(
                                    "The `%s` method cannot be used with together with the `postProcessing` block.",
                                    methodName);
                    break;
                default:
                    throw new AssertionError("Unknown value " + used);
            }
            issueReporter.reportError(Type.GENERIC, message, methodName);
        }
    }

    @Override
    public BuildType initWith(com.android.builder.model.BuildType that) {
        // we need to avoid doing this because of Property objects that cannot
        // be set from themselves
        if (that == this) {
            return this;
        }
        dslChecksEnabled.set(false);
        try {
            return (BuildType) super.initWith(that);
        } finally {
            dslChecksEnabled.set(true);
        }
    }
}
