/*
 * Copyright 2014-present Facebook, Inc.
 *
 * 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.facebook.buck.android;

import com.facebook.buck.android.AndroidBinary.ExopackageMode;
import com.facebook.buck.android.AndroidBinary.PackageType;
import com.facebook.buck.android.AndroidBinary.TargetCpuType;
import com.facebook.buck.android.FilterResourcesStep.ResourceFilter;
import com.facebook.buck.android.ResourcesFilter.ResourceCompressionMode;
import com.facebook.buck.dalvik.ZipSplitter.DexSplitStrategy;
import com.facebook.buck.java.JavaLibrary;
import com.facebook.buck.java.JavacOptions;
import com.facebook.buck.java.Keystore;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.HasBuildTarget;
import com.facebook.buck.parser.BuildTargetParser;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.BuildRuleType;
import com.facebook.buck.rules.BuildRules;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.Hint;
import com.facebook.buck.rules.ImmutableBuildRuleType;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.coercer.BuildConfigFields;
import com.facebook.buck.rules.macros.ExecutableMacroExpander;
import com.facebook.buck.rules.macros.LocationMacroExpander;
import com.facebook.buck.rules.macros.MacroExpander;
import com.facebook.buck.rules.macros.MacroHandler;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Suppliers;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AndroidBinaryDescription implements Description<AndroidBinaryDescription.Arg> {

  public static final BuildRuleType TYPE = ImmutableBuildRuleType.of("android_binary");

  /**
   * By default, assume we have 5MB of linear alloc,
   * 1MB of which is taken up by the framework, so that leaves 4MB.
   */
  private static final long DEFAULT_LINEAR_ALLOC_HARD_LIMIT = 4 * 1024 * 1024;

  private static final BuildTargetParser BUILD_TARGET_PARSER = new BuildTargetParser();
  private static final MacroHandler MACRO_HANDLER =
      new MacroHandler(
          ImmutableMap.<String, MacroExpander>of(
              "exe", new ExecutableMacroExpander(BUILD_TARGET_PARSER),
              "location", new LocationMacroExpander(BUILD_TARGET_PARSER)));

  private static final Pattern COUNTRY_LOCALE_PATTERN = Pattern.compile("([a-z]{2})-[A-Z]{2}");

  private final JavacOptions javacOptions;
  private final ProGuardConfig proGuardConfig;
  private final ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms;

  public AndroidBinaryDescription(
      JavacOptions javacOptions,
      ProGuardConfig proGuardConfig,
      ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms) {
    this.javacOptions = javacOptions;
    this.proGuardConfig = proGuardConfig;
    this.nativePlatforms = nativePlatforms;
  }

  @Override
  public BuildRuleType getBuildRuleType() {
    return TYPE;
  }

  @Override
  public Arg createUnpopulatedConstructorArg() {
    return new Arg();
  }

  @Override
  public <A extends Arg> AndroidBinary createBuildRule(
      final BuildRuleParams params,
      final BuildRuleResolver resolver,
      A args) {
    BuildRule keystore = resolver.getRule(args.keystore);
    if (!(keystore instanceof Keystore)) {
      throw new HumanReadableException(
          "In %s, keystore='%s' must be a keystore() but was %s().",
          params.getBuildTarget(),
          keystore.getFullyQualifiedName(),
          keystore.getType().getName());
    }

    ProGuardObfuscateStep.SdkProguardType androidSdkProguardConfig =
        args.androidSdkProguardConfig.or(ProGuardObfuscateStep.SdkProguardType.DEFAULT);

    // If the old boolean version of this argument was specified, make sure the new form
    // was not specified, and allow the old form to override the default.
    if (args.useAndroidProguardConfigWithOptimizations.isPresent()) {
      Preconditions.checkArgument(
          !args.androidSdkProguardConfig.isPresent(),
          "The deprecated use_android_proguard_config_with_optimizations parameter" +
              " cannot be used with android_sdk_proguard_config.");
      androidSdkProguardConfig = args.useAndroidProguardConfigWithOptimizations.or(false)
          ? ProGuardObfuscateStep.SdkProguardType.OPTIMIZED
          : ProGuardObfuscateStep.SdkProguardType.DEFAULT;
    }

    EnumSet<ExopackageMode> exopackageModes = EnumSet.noneOf(ExopackageMode.class);
    if (args.exopackageModes.isPresent() && !args.exopackageModes.get().isEmpty()) {
      exopackageModes = EnumSet.copyOf(args.exopackageModes.get());
    } else if (args.exopackage.or(false)) {
      exopackageModes = EnumSet.of(ExopackageMode.SECONDARY_DEX);
    }

    DexSplitMode dexSplitMode = createDexSplitMode(args, exopackageModes);

    boolean allowNonExistentRule =
          false;
    ImmutableSortedSet<BuildRule> buildRulesToExcludeFromDex = BuildRules.toBuildRulesFor(
        params.getBuildTarget(),
        resolver,
        args.noDx.or(ImmutableSet.<BuildTarget>of()),
        allowNonExistentRule);
    ImmutableSortedSet<JavaLibrary> rulesToExcludeFromDex =
        FluentIterable.from(buildRulesToExcludeFromDex)
            .filter(JavaLibrary.class)
            .toSortedSet(HasBuildTarget.BUILD_TARGET_COMPARATOR);

    PackageType packageType = getPackageType(args);
    boolean shouldPreDex = !args.disablePreDex.or(false) &&
        PackageType.DEBUG.equals(packageType) &&
        !args.preprocessJavaClassesBash.isPresent();

    ResourceCompressionMode compressionMode = getCompressionMode(args);
    ResourceFilter resourceFilter =
        new ResourceFilter(args.resourceFilter.or(ImmutableList.<String>of()));

    AndroidBinaryGraphEnhancer graphEnhancer = new AndroidBinaryGraphEnhancer(
        params,
        resolver,
        compressionMode,
        resourceFilter,
        addFallbackLocales(args.locales.or(ImmutableSet.<String>of())),
        args.manifest,
        packageType,
        ImmutableSet.copyOf(args.cpuFilters.get()),
        args.buildStringSourceMap.or(false),
        shouldPreDex,
        AndroidBinary.getPrimaryDexPath(params.getBuildTarget()),
        dexSplitMode,
        ImmutableSet.copyOf(args.noDx.or(ImmutableSet.<BuildTarget>of())),
        /* resourcesToExclude */ ImmutableSet.<BuildTarget>of(),
        args.skipCrunchPngs.or(false),
        javacOptions,
        exopackageModes,
        (Keystore) keystore,
        args.buildConfigValues.get(),
        args.buildConfigValuesFile,
        nativePlatforms);
    AndroidGraphEnhancementResult result =
        graphEnhancer.createAdditionalBuildables();

    return new AndroidBinary(
        params.copyWithExtraDeps(Suppliers.ofInstance(result.getFinalDeps())),
        new SourcePathResolver(resolver),
        proGuardConfig.getProguardJarOverride(),
        proGuardConfig.getProguardMaxHeapSize(),
        args.manifest,
        (Keystore) keystore,
        packageType,
        dexSplitMode,
        args.noDx.or(ImmutableSet.<BuildTarget>of()),
        androidSdkProguardConfig,
        args.optimizationPasses,
        args.proguardConfig,
        compressionMode,
        args.cpuFilters.get(),
        resourceFilter,
        exopackageModes,
        resolver.getAllRules(
            args.preprocessJavaClassesDeps.or(ImmutableSortedSet.<BuildTarget>of())),
        MACRO_HANDLER.getExpander(
            params.getBuildTarget(),
            resolver,
            params.getProjectFilesystem()),
        args.preprocessJavaClassesBash,
        rulesToExcludeFromDex,
        result);
  }

  private DexSplitMode createDexSplitMode(Arg args, EnumSet<ExopackageMode> exopackageModes) {
    // Exopackage builds default to JAR, otherwise, default to RAW.
    DexStore defaultDexStore = ExopackageMode.enabledForSecondaryDexes(exopackageModes)
        ? DexStore.JAR
        : DexStore.RAW;
    DexSplitStrategy dexSplitStrategy = args.minimizePrimaryDexSize.or(false)
        ? DexSplitStrategy.MINIMIZE_PRIMARY_DEX_SIZE
        : DexSplitStrategy.MAXIMIZE_PRIMARY_DEX_SIZE;
    return new DexSplitMode(
        args.useSplitDex.or(false),
        dexSplitStrategy,
        args.dexCompression.or(defaultDexStore),
        args.useLinearAllocSplitDex.or(false),
        args.linearAllocHardLimit.or(DEFAULT_LINEAR_ALLOC_HARD_LIMIT),
        args.primaryDexPatterns.or(ImmutableList.<String>of()),
        args.primaryDexClassesFile,
        args.primaryDexScenarioFile,
        args.primaryDexScenarioOverflowAllowed.or(false),
        args.secondaryDexHeadClassesFile,
        args.secondaryDexTailClassesFile);
  }

  private PackageType getPackageType(Arg args) {
    if (!args.packageType.isPresent()) {
      return PackageType.DEBUG;
    }
    return PackageType.valueOf(args.packageType.get().toUpperCase());
  }

  private ResourceCompressionMode getCompressionMode(Arg args) {
    if (!args.resourceCompression.isPresent()) {
      return ResourceCompressionMode.DISABLED;
    }
    return ResourceCompressionMode.valueOf(args.resourceCompression.get().toUpperCase());
  }

  private ImmutableSet<String> addFallbackLocales(ImmutableSet<String> locales) {
    ImmutableSet.Builder<String> allLocales = ImmutableSet.builder();
    for (String locale : locales) {
      allLocales.add(locale);
      Matcher matcher = COUNTRY_LOCALE_PATTERN.matcher(locale);
      if (matcher.matches()) {
        allLocales.add(matcher.group(1));
      }
    }
    return allLocales.build();
  }

  @SuppressFieldNotInitialized
  public static class Arg {
    public SourcePath manifest;
    // TODO(mbolin): Support for this field will be dropped as it is no longer used. Keeping it
    // around is misleading. A deprecation warning should be printed if it is set.
    public Optional<String> target;
    public BuildTarget keystore;
    public Optional<String> packageType;
    @Hint(isDep = false) public Optional<Set<BuildTarget>> noDx;
    public Optional<Boolean> useSplitDex;
    public Optional<Boolean> useLinearAllocSplitDex;
    public Optional<Boolean> minimizePrimaryDexSize;
    public Optional<Boolean> disablePreDex;
    // TODO(natthu): mark this as deprecated.
    public Optional<Boolean> exopackage;
    public Optional<Set<ExopackageMode>> exopackageModes;
    public Optional<DexStore> dexCompression;
    public Optional<ProGuardObfuscateStep.SdkProguardType> androidSdkProguardConfig;
    public Optional<Boolean> useAndroidProguardConfigWithOptimizations;
    public Optional<Integer> optimizationPasses;
    public Optional<SourcePath> proguardConfig;
    public Optional<String> resourceCompression;
    public Optional<Boolean> skipCrunchPngs;
    public Optional<List<String>> primaryDexPatterns;
    public Optional<SourcePath> primaryDexClassesFile;
    public Optional<SourcePath> primaryDexScenarioFile;
    public Optional<Boolean> primaryDexScenarioOverflowAllowed;
    public Optional<SourcePath> secondaryDexHeadClassesFile;
    public Optional<SourcePath> secondaryDexTailClassesFile;
    public Optional<Long> linearAllocHardLimit;
    public Optional<List<String>> resourceFilter;
    public Optional<ImmutableSet<String>> locales;
    public Optional<Boolean> buildStringSourceMap;
    public Optional<Set<TargetCpuType>> cpuFilters;
    public Optional<ImmutableSortedSet<BuildTarget>> preprocessJavaClassesDeps;
    public Optional<String> preprocessJavaClassesBash;

    /** This will never be absent after this Arg is populated. */
    public Optional<BuildConfigFields> buildConfigValues;

    public Optional<SourcePath> buildConfigValuesFile;

    public Optional<ImmutableSortedSet<BuildTarget>> deps;
  }
}
