/*
 * Copyright 2015-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.io.ProjectFilesystem;
import com.facebook.buck.java.JavaBinaryDescription;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.Flavor;
import com.facebook.buck.model.ImmutableFlavor;
import com.facebook.buck.model.UnflavoredBuildTarget;
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.BuildTargetSourcePath;
import com.facebook.buck.rules.Description;
import com.facebook.buck.rules.ImmutableBuildRuleType;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Optional;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.nio.file.Path;
import java.util.Collection;

/**
 * Description for a {@link BuildRule} that generates an {@code .aar} file.
 * <p>
 * This represents an Android Library Project packaged as an {@code .aar} bundle as specified by:
 * <a> http://tools.android.com/tech-docs/new-build-system/aar-format </>.
 * <p>
 * Note that the {@code aar} may be specified as a {@link SourcePath}, so it could be either
 * a binary {@code .aar} file checked into version control, or a zip file that conforms to the
 * {@code .aar} specification that is generated by another build rule.
 */
public class AndroidAarDescription implements Description<AndroidAarDescription.Arg> {

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

  private static final Flavor AAR_ANDROID_MANIFEST_FLAVOR =
      ImmutableFlavor.of("aar_android_manifest");
  private static final Flavor AAR_ASSEMBLE_RESOURCE_FLAVOR =
      ImmutableFlavor.of("aar_assemble_resource");
  private static final Flavor AAR_ASSEMBLE_ASSETS_FLAVOR =
      ImmutableFlavor.of("aar_assemble_assets");
  private static final Flavor AAR_ANDROID_RESOURCE_FLAVOR =
      ImmutableFlavor.of("aar_android_resource");
  private static final Flavor AAR_JAVA_BINARY_FLAVOR =
      ImmutableFlavor.of("aar_java_binary");

  private final AndroidManifestDescription androidManifestDescription;
  private final JavaBinaryDescription javaBinaryDescription;

  public AndroidAarDescription(
      AndroidManifestDescription androidManifestDescription,
      JavaBinaryDescription javaBinaryDescription) {
    this.androidManifestDescription = androidManifestDescription;
    this.javaBinaryDescription = javaBinaryDescription;
  }

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

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

  @Override
  public <A extends Arg> BuildRule createBuildRule(
      BuildRuleParams originalBuildRuleParams,
      BuildRuleResolver resolver,
      A args) {

    UnflavoredBuildTarget originalBuildTarget =
        originalBuildRuleParams.getBuildTarget().checkUnflavored();
    SourcePathResolver pathResolver = new SourcePathResolver(resolver);
    ImmutableList.Builder<BuildRule> depRules = ImmutableList.builder();

    /* android_manifest */
    AndroidManifestDescription.Arg androidManifestArgs =
        androidManifestDescription.createUnpopulatedConstructorArg();
    androidManifestArgs.skeleton = args.manifestSkeleton;
    androidManifestArgs.deps = args.deps;

    BuildRuleParams androidManifestParams = originalBuildRuleParams.copyWithChanges(
        AndroidManifestDescription.TYPE,
        BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ANDROID_MANIFEST_FLAVOR),
        Suppliers.ofInstance(originalBuildRuleParams.getDeclaredDeps()),
        Suppliers.ofInstance(originalBuildRuleParams.getExtraDeps()));

    AndroidManifest manifest = androidManifestDescription.createBuildRule(
        androidManifestParams,
        resolver,
        androidManifestArgs);
    depRules.add(resolver.addToIndex(manifest));

    /* assemble dirs */
    AndroidPackageableCollector collector =
        new AndroidPackageableCollector(
            originalBuildRuleParams.getBuildTarget(),
            ImmutableSet.<BuildTarget>of(),
            ImmutableSet.<BuildTarget>of());
    collector.addPackageables(AndroidPackageableCollector.getPackageableRules(
            originalBuildRuleParams.getDeps()));
    ImmutableAndroidPackageableCollection packageableCollection = collector.build();

    ImmutableSortedSet<BuildRule> androidResourceDeclaredDeps =
        AndroidResourceHelper.androidResOnly(originalBuildRuleParams.getDeclaredDeps());
    ImmutableSortedSet<BuildRule> androidResourceExtraDeps =
        AndroidResourceHelper.androidResOnly(originalBuildRuleParams.getExtraDeps());

    BuildRuleParams assembleAssetsParams = originalBuildRuleParams.copyWithChanges(
        originalBuildRuleParams.getBuildRuleType(),
        BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ASSEMBLE_ASSETS_FLAVOR),
        Suppliers.ofInstance(androidResourceDeclaredDeps),
        Suppliers.ofInstance(androidResourceExtraDeps));
    ImmutableCollection<SourcePath> assetsDirectories = getSourcePathForDirectories(
        assembleAssetsParams.getProjectFilesystem(),
        assembleAssetsParams.getBuildTarget(),
        packageableCollection.getAssetsDirectories());
    AssembleDirectories assembleAssetsDirectories = new AssembleDirectories(
        assembleAssetsParams,
        pathResolver,
        assetsDirectories);
    depRules.add(resolver.addToIndex(assembleAssetsDirectories));

    BuildRuleParams assembleResourceParams = originalBuildRuleParams.copyWithChanges(
        originalBuildRuleParams.getBuildRuleType(),
        BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ASSEMBLE_RESOURCE_FLAVOR),
        Suppliers.ofInstance(androidResourceDeclaredDeps),
        Suppliers.ofInstance(androidResourceExtraDeps));
    ImmutableCollection<SourcePath> resDirectories = getSourcePathForDirectories(
        assembleResourceParams.getProjectFilesystem(),
        assembleResourceParams.getBuildTarget(),
        packageableCollection.getResourceDetails().getResourceDirectories());
    AssembleDirectories assembleResourceDirectories = new AssembleDirectories(
        assembleResourceParams,
        pathResolver,
        resDirectories);
    depRules.add(resolver.addToIndex(assembleResourceDirectories));

    /* android_resource */
    BuildRuleParams androidResourceParams = originalBuildRuleParams.copyWithChanges(
        AndroidLibraryDescription.TYPE,
        BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_ANDROID_RESOURCE_FLAVOR),
        Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of(
                manifest,
                assembleAssetsDirectories,
                assembleResourceDirectories)),
        Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));

    AndroidResource androidResource = new AndroidResource(
        androidResourceParams,
        pathResolver,
        /* deps */ ImmutableSortedSet.copyOf(depRules.build()),
        assembleResourceDirectories.getPathToOutputFile(),
        /* resSrcs */ ImmutableSortedSet.<Path>of(),
        /* rDotJavaPackage */ null,
        assembleAssetsDirectories.getPathToOutputFile(),
        /* assetsSrcs */ ImmutableSortedSet.<Path>of(),
        new BuildTargetSourcePath(manifest.getProjectFilesystem(), manifest.getBuildTarget()),
        /* hasWhitelistedStrings */ false);
    depRules.add(resolver.addToIndex(androidResource));

    /* java_binary */
    JavaBinaryDescription.Args javaBinaryArgs =
        javaBinaryDescription.createUnpopulatedConstructorArg();
    javaBinaryArgs.deps = args.deps;
    javaBinaryArgs.mainClass = Optional.absent();
    javaBinaryArgs.manifestFile = Optional.absent();
    javaBinaryArgs.mergeManifests = Optional.absent();
    javaBinaryArgs.metaInfDirectory = Optional.absent();
    javaBinaryArgs.blacklist = Optional.absent();

    BuildRuleParams javaBinaryParams = originalBuildRuleParams.copyWithChanges(
        JavaBinaryDescription.TYPE,
        BuildTargets.createFlavoredBuildTarget(originalBuildTarget, AAR_JAVA_BINARY_FLAVOR),
        Suppliers.ofInstance(originalBuildRuleParams.getDeclaredDeps()),
        Suppliers.ofInstance(originalBuildRuleParams.getExtraDeps()));

    BuildRule javaBinary = javaBinaryDescription.createBuildRule(
        javaBinaryParams,
        resolver,
        javaBinaryArgs);
    depRules.add(resolver.addToIndex(javaBinary));

    /* android_aar */
    depRules.addAll(
        getTargetsAsRules(
            packageableCollection.getNativeLibsTargets(),
            BuildTarget.of(originalBuildTarget),
            resolver));

    BuildRuleParams androidAarParams = originalBuildRuleParams.copyWithChanges(
        TYPE,
        BuildTarget.of(originalBuildTarget),
        Suppliers.ofInstance(ImmutableSortedSet.copyOf(depRules.build())),
        Suppliers.ofInstance(ImmutableSortedSet.<BuildRule>of()));

    return new AndroidAar(
        androidAarParams,
        pathResolver,
        manifest,
        androidResource,
        javaBinary,
        assembleResourceDirectories,
        assembleAssetsDirectories,
        packageableCollection.getNativeLibAssetsDirectories(),
        packageableCollection.getNativeLibsDirectories());
  }

  private ImmutableSortedSet<BuildRule> getTargetsAsRules(
      Collection<BuildTarget> buildTargets,
      BuildTarget originalBuildTarget,
      BuildRuleResolver ruleResolver) {
    return BuildRules.toBuildRulesFor(
        originalBuildTarget,
        ruleResolver,
        buildTargets,
        /* allowNonExistentRules */ false);
  }

  private ImmutableList<SourcePath> getSourcePathForDirectories(
      ProjectFilesystem projectFilesystem,
      BuildTarget buildTarget,
      ImmutableCollection<Path> directories) {
    ImmutableList.Builder<SourcePath> builder = ImmutableList.builder();
    for (Path directory : directories) {
      builder.add(new BuildTargetSourcePath(projectFilesystem, buildTarget, directory));
    }
    return builder.build();
  }

  @SuppressFieldNotInitialized
  public static class Arg extends AndroidLibraryDescription.Arg {
    public SourcePath manifestSkeleton;
  }
}
