/*
 * 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.android.common.SdkConstants;
import com.facebook.buck.android.AndroidBinary.TargetCpuType;
import com.facebook.buck.cxx.ObjcopyStep;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTargets;
import com.facebook.buck.model.Pair;
import com.facebook.buck.rules.AbstractBuildRule;
import com.facebook.buck.rules.BuildContext;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildableContext;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePath;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.step.AbstractExecutionStep;
import com.facebook.buck.step.ExecutionContext;
import com.facebook.buck.step.Step;
import com.facebook.buck.step.fs.CopyStep;
import com.facebook.buck.step.fs.MakeCleanDirectoryStep;
import com.facebook.buck.step.fs.MkdirStep;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * A {@link com.facebook.buck.rules.BuildRule} that gathers shared objects generated by
 * {@code ndk_library} and {@code prebuilt_native_library} rules into a directory. It also hashes
 * the shared objects collected and stores this metadata in a text file, to be used later by
 * {@link com.facebook.buck.cli.ExopackageInstaller}.
 */
public class CopyNativeLibraries extends AbstractBuildRule {

  private final ImmutableSet<Path> nativeLibDirectories;
  private final ImmutableSet<TargetCpuType> cpuFilters;

  /**
   * A map of native libraries to copy in which are already filtered using the above CPU filter.
   * The keys of the map are the tuple of {@link TargetCpuType} and shared library SONAME
   * (e.g. <"x86", "libtest.so">), and the values of the map are the full paths to the libraries.
   */
  private final ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms;
  private final ImmutableMap<Pair<TargetCpuType, String>, SourcePath> filteredNativeLibraries;

  protected CopyNativeLibraries(
      BuildRuleParams buildRuleParams,
      SourcePathResolver resolver,
      ImmutableSet<Path> nativeLibDirectories,
      ImmutableSet<TargetCpuType> cpuFilters,
      ImmutableMap<TargetCpuType, NdkCxxPlatform> nativePlatforms,
      ImmutableMap<Pair<TargetCpuType, String>, SourcePath> filteredNativeLibraries) {
    super(buildRuleParams, resolver);
    this.nativeLibDirectories = nativeLibDirectories;
    this.cpuFilters = cpuFilters;
    this.filteredNativeLibraries = filteredNativeLibraries;
    this.nativePlatforms = nativePlatforms;
    Preconditions.checkArgument(
        !nativeLibDirectories.isEmpty() || !filteredNativeLibraries.isEmpty(),
        "There should be at least one native library to copy.");
  }

  public Path getPathToNativeLibsDir() {
    return getBinPath().resolve("libs");
  }

  public Path getPathToMetadataTxt() {
    return getBinPath().resolve("metadata.txt");
  }

  private Path getBinPath() {
    return BuildTargets.getBinPath(getBuildTarget(), "__native_libs_%s__");
  }

  @Override
  protected ImmutableCollection<Path> getInputsToCompareToOutput() {
    return ImmutableList.of();
  }

  @Override
  protected RuleKey.Builder appendDetailsToRuleKey(RuleKey.Builder builder) {
    builder.setReflectively("cpuFilters", cpuFilters);

    // Hash in the pre-filtered native libraries we're pulling in.
    ImmutableSortedMap<Pair<TargetCpuType, String>, SourcePath> sortedLibs =
        ImmutableSortedMap.<Pair<TargetCpuType, String>, SourcePath>orderedBy(
                Pair.<TargetCpuType, String>comparator())
            .putAll(filteredNativeLibraries)
            .build();
    for (Map.Entry<Pair<TargetCpuType, String>, SourcePath> entry : sortedLibs.entrySet()) {
      builder.setReflectively(
          String.format("lib(%s, %s)", entry.getKey().getFirst(), entry.getKey().getSecond()),
          entry.getValue());
    }

    return builder;
  }

  @Override
  public ImmutableList<Step> getBuildSteps(
      BuildContext context,
      BuildableContext buildableContext) {
    ImmutableList.Builder<Step> steps = ImmutableList.builder();

    final Path pathToNativeLibs = getPathToNativeLibsDir();
    steps.add(new MakeCleanDirectoryStep(pathToNativeLibs));

    for (Path nativeLibDir : nativeLibDirectories.asList().reverse()) {
      copyNativeLibrary(nativeLibDir, pathToNativeLibs, cpuFilters, steps);
    }

    // Copy in the pre-filtered native libraries.
    for (Map.Entry<Pair<TargetCpuType, String>, SourcePath> entry :
         filteredNativeLibraries.entrySet()) {
      Optional<String> abiDirectoryComponent = getAbiDirectoryComponent(entry.getKey().getFirst());
      Preconditions.checkState(abiDirectoryComponent.isPresent());
      Path destination =
          pathToNativeLibs
              .resolve(abiDirectoryComponent.get())
              .resolve(entry.getKey().getSecond());
      NdkCxxPlatform platform =
          Preconditions.checkNotNull(nativePlatforms.get(entry.getKey().getFirst()));
      Path objcopy = platform.getObjcopy();
      steps.add(new MkdirStep(destination.getParent()));
      steps.add(
          new ObjcopyStep(
              objcopy,
              ImmutableList.of("--strip-unneeded"),
              getResolver().getPath(entry.getValue()),
              destination));
    }

    final Path pathToMetadataTxt = getPathToMetadataTxt();
    steps.add(
        new AbstractExecutionStep("hash_native_libs") {
          @Override
          public int execute(ExecutionContext context) {
            ProjectFilesystem filesystem = context.getProjectFilesystem();
            ImmutableList.Builder<String> metadataLines = ImmutableList.builder();
            try {
              for (Path nativeLib : filesystem.getFilesUnderPath(pathToNativeLibs)) {
                String filesha1 = filesystem.computeSha1(nativeLib);
                Path relativePath = pathToNativeLibs.relativize(nativeLib);
                metadataLines.add(String.format("%s %s", relativePath.toString(), filesha1));
              }
              filesystem.writeLinesToPath(metadataLines.build(), pathToMetadataTxt);
            } catch (IOException e) {
              context.logError(e, "There was an error hashing native libraries.");
              return 1;
            }
            return 0;
          }
        });

    buildableContext.recordArtifactsInDirectory(pathToNativeLibs);
    buildableContext.recordArtifact(pathToMetadataTxt);

    return steps.build();
  }

  @Nullable
  @Override
  public Path getPathToOutputFile() {
    return null;
  }

  public static void copyNativeLibrary(Path sourceDir,
      final Path destinationDir,
      ImmutableSet<TargetCpuType> cpuFilters,
      ImmutableList.Builder<Step> steps) {

    if (cpuFilters.isEmpty()) {
      steps.add(
          CopyStep.forDirectory(
              sourceDir,
              destinationDir,
              CopyStep.DirectoryMode.CONTENTS_ONLY));
    } else {
      for (TargetCpuType cpuType : cpuFilters) {
        Optional<String> abiDirectoryComponent = getAbiDirectoryComponent(cpuType);
        Preconditions.checkState(abiDirectoryComponent.isPresent());

        final Path libSourceDir = sourceDir.resolve(abiDirectoryComponent.get());
        Path libDestinationDir = destinationDir.resolve(abiDirectoryComponent.get());

        final MkdirStep mkDirStep = new MkdirStep(libDestinationDir);
        final CopyStep copyStep = CopyStep.forDirectory(
            libSourceDir,
            libDestinationDir,
            CopyStep.DirectoryMode.CONTENTS_ONLY);
        steps.add(
            new Step() {
              @Override
              public int execute(ExecutionContext context) {
                if (!context.getProjectFilesystem().exists(libSourceDir)) {
                  return 0;
                }
                if (mkDirStep.execute(context) == 0 && copyStep.execute(context) == 0) {
                  return 0;
                }
                return 1;
              }

              @Override
              public String getShortName() {
                return "copy_native_libraries";
              }

              @Override
              public String getDescription(ExecutionContext context) {
                ImmutableList.Builder<String> stringBuilder = ImmutableList.builder();
                stringBuilder.add(String.format("[ -d %s ]", libSourceDir.toString()));
                stringBuilder.add(mkDirStep.getDescription(context));
                stringBuilder.add(copyStep.getDescription(context));
                return Joiner.on(" && ").join(stringBuilder.build());
              }
            });
      }
    }

    // Rename native files named like "*-disguised-exe" to "lib*.so" so they will be unpacked
    // by the Android package installer.  Then they can be executed like normal binaries
    // on the device.
    steps.add(
        new AbstractExecutionStep("rename_native_executables") {
          @Override
          public int execute(ExecutionContext context) {

            ProjectFilesystem filesystem = context.getProjectFilesystem();
            final ImmutableSet.Builder<Path> executablesBuilder = ImmutableSet.builder();
            try {
              filesystem.walkRelativeFileTree(destinationDir, new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                        throws IOException {
                      if (file.toString().endsWith("-disguised-exe")) {
                        executablesBuilder.add(file);
                      }
                      return FileVisitResult.CONTINUE;
                    }
                  });
              for (Path exePath : executablesBuilder.build()) {
                Path fakeSoPath = Paths.get(
                    exePath.toString().replaceAll("/([^/]+)-disguised-exe$", "/lib$1.so"));
                filesystem.move(exePath, fakeSoPath);
              }
            } catch (IOException e) {
              context.logError(e, "Renaming native executables failed.");
              return 1;
            }
            return 0;
          }
        });
  }

  /**
   * Native libraries compiled for different CPU architectures are placed in the
   * respective ABI subdirectories, such as 'armeabi', 'armeabi-v7a', 'x86' and 'mips'.
   * This looks at the cpu filter and returns the correct subdirectory. If cpu filter is
   * not present or not supported, returns Optional.absent();
   */
  private static Optional<String> getAbiDirectoryComponent(TargetCpuType cpuType) {
    String component = null;
    if (cpuType.equals(TargetCpuType.ARM)) {
      component = SdkConstants.ABI_ARMEABI;
    } else if (cpuType.equals(TargetCpuType.ARMV7)) {
      component = SdkConstants.ABI_ARMEABI_V7A;
    } else if (cpuType.equals(TargetCpuType.X86)) {
      component = SdkConstants.ABI_INTEL_ATOM;
    } else if (cpuType.equals(TargetCpuType.MIPS)) {
      component = SdkConstants.ABI_MIPS;
    }
    return Optional.fromNullable(component);
  }
}
