/*
 * Copyright 2013-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.io;

import com.facebook.buck.util.BuckConstant;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;

import javax.annotation.Nullable;

public class MorePaths {

  /**
   * Returns true iff a path on the filesystem exists, is a regular file, and is executable.
   */
  public static final Function<Path, Boolean> DEFAULT_PATH_IS_EXECUTABLE_CHECKER =
      new Function<Path, Boolean>() {
        @Override
        public Boolean apply(Path path) {
          return Files.isRegularFile(path) &&
              Files.isExecutable(path);
        }
      };

  /** Utility class: do not instantiate. */
  private MorePaths() {}

  public static final Function<String, Path> TO_PATH = new Function<String, Path>() {
    @Override
    public Path apply(String path) {
      return Paths.get(path);
    }
  };

  public static String pathWithUnixSeparators(String path) {
    return pathWithUnixSeparators(Paths.get(path));
  }

  public static String pathWithUnixSeparators(Path path) {
    return path.toString().replace("\\", "/");
  }

  /**
   * @param toMakeAbsolute The {@link Path} to act upon.
   * @return The Path, made absolute and normalized.
   */
  public static Path absolutify(Path toMakeAbsolute) {
    return toMakeAbsolute.toAbsolutePath().normalize();
  }

  /**
   * Get the path of a file relative to a base directory.
   *
   * @param path must reference a file, not a directory.
   * @param baseDir must reference a directory that is relative to a common directory with the path.
   *     may be null if referencing the same directory as the path.
   * @return the relative path of path from the directory baseDir.
   */
  public static Path getRelativePath(Path path, @Nullable Path baseDir) {
    if (baseDir == null) {
      // This allows callers to use this method with "file.parent()" for files from the project
      // root dir.
      baseDir = Paths.get("");
    }
    Preconditions.checkArgument(!path.isAbsolute(),
        "Path must be relative: %s.", path);
    Preconditions.checkArgument(!baseDir.isAbsolute(),
        "Path must be relative: %s.", baseDir);
    return relativize(baseDir, path);
  }

  /**
   * Get a relative path from path1 to path2, first normalizing each path.
   *
   * This method is a workaround for JDK-6925169 (Path.relativize
   * returns incorrect result if path contains "." or "..").
   */
  public static Path relativize(Path path1, Path path2) {
    Path emptyPath = Paths.get("");

    Preconditions.checkArgument(
        path1.isAbsolute() == path2.isAbsolute(),
        "Both paths must be absolute or both paths must be relative. (%s is %s, %s is %s)",
        path1,
        path1.isAbsolute() ? "absolute" : "relative",
        path2,
        path2.isAbsolute() ? "absolute" : "relative");

    // Work around JDK-8037945 (Paths.get("").normalize() throws ArrayIndexOutOfBoundsException).
    if (!path1.equals(emptyPath)) {
      path1 = path1.normalize();
    }
    if (!path2.equals(emptyPath)) {
      path2 = path2.normalize();
    }

    // On Windows, if path1 is "" then Path.relativize returns ../path2 instead of path2 or ./path2
    if (path1.equals(emptyPath)) {
      return path2;
    }
    return path1.relativize(path2);
  }

  /**
   * Creates a symlink at
   * {@code projectFilesystem.getRootPath().resolve(pathToDesiredLinkUnderProjectRoot)} that
   * points to {@code projectFilesystem.getRootPath().resolve(pathToExistingFileUnderProjectRoot)}
   * using a relative symlink.
   *
   * @param pathToDesiredLinkUnderProjectRoot must reference a file, not a directory.
   * @param pathToExistingFileUnderProjectRoot must reference a file, not a directory.
   * @return the relative path from the new symlink that was created to the existing file.
   */
  public static Path createRelativeSymlink(
      Path pathToDesiredLinkUnderProjectRoot,
      Path pathToExistingFileUnderProjectRoot,
      ProjectFilesystem projectFilesystem) throws IOException {
    return createRelativeSymlink(
        pathToDesiredLinkUnderProjectRoot,
        pathToExistingFileUnderProjectRoot,
        projectFilesystem.getRootPath());
  }

  /**
   * Creates a symlink at {@code pathToProjectRoot.resolve(pathToDesiredLinkUnderProjectRoot)} that
   * points to {@code pathToProjectRoot.resolve(pathToExistingFileUnderProjectRoot)} using a
   * relative symlink. Both params must be relative to the project root.
   *
   * @param pathToDesiredLinkUnderProjectRoot must reference a file, not a directory.
   * @param pathToExistingFileUnderProjectRoot must reference a file, not a directory.
   * @return the relative path from the new symlink that was created to the existing file.
   */
  public static Path createRelativeSymlink(
      Path pathToDesiredLinkUnderProjectRoot,
      Path pathToExistingFileUnderProjectRoot,
      Path pathToProjectRoot) throws IOException {
    Path target = getRelativePath(
        pathToExistingFileUnderProjectRoot,
        pathToDesiredLinkUnderProjectRoot.getParent());
    Files.createSymbolicLink(pathToProjectRoot.resolve(pathToDesiredLinkUnderProjectRoot), target);
    return target;
  }

  /**
   * Convert a set of input file paths as strings to {@link Path} objects.
   */
  public static ImmutableSortedSet<Path> asPaths(Iterable<String> paths) {
    ImmutableSortedSet.Builder<Path> builder = ImmutableSortedSet.naturalOrder();
    for (String path : paths) {
      builder.add(TO_PATH.apply(path));
    }
    return builder.build();
  }

  /**
   * Filters out {@link Path} objects from {@code paths} that aren't a subpath of {@code root} and
   * returns a set of paths relative to {@code root}.
   */
  public static ImmutableSet<Path> filterForSubpaths(Iterable<Path> paths, final Path root) {
    final Path normalizedRoot = root.toAbsolutePath().normalize();
    return FluentIterable.from(paths)
        .filter(new Predicate<Path>() {
          @Override
          public boolean apply(Path input) {
            if (input.isAbsolute()) {
              return input.normalize().startsWith(normalizedRoot);
            } else {
              return true;
            }
          }
        })
        .transform(new Function<Path, Path>() {
          @Override
          public Path apply(Path input) {
            if (input.isAbsolute()) {
              return relativize(normalizedRoot, input);
            } else {
              return input;
            }
          }
        })
        .toSet();
  }

  /**
   * @return Whether the input path directs to a file in the buck generated files folder.
   */
  public static boolean isGeneratedFile(Path pathRelativeToProjectRoot) {
    return pathRelativeToProjectRoot.startsWith(BuckConstant.GEN_PATH);
  }

  /**
   * Expands "~/foo" into "/home/zuck/foo". Returns regular paths unmodified.
   */
  public static Path expandHomeDir(Path path) {
    if (!path.startsWith("~")) {
      return path;
    }
    Path homePath = Paths.get(System.getProperty("user.home"));
    if (path.equals(Paths.get("~"))) {
      return homePath;
    }
    return homePath.resolve(path.subpath(1, path.getNameCount()));
  }

  public static boolean fileContentsDiffer(
      InputStream contents,
      Path path,
      ProjectFilesystem projectFilesystem) throws IOException {
    try {
      // Hash the contents of the file at path so we don't have to pull the whole thing into memory.
      MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
      byte[] pathDigest;
      try (InputStream is = projectFilesystem.newFileInputStream(path)) {
          pathDigest = inputStreamDigest(is, sha1);
      }
      // Hash 'contents' and see if the two differ.
      sha1.reset();
      byte[] contentsDigest = inputStreamDigest(contents, sha1);
      return !Arrays.equals(pathDigest, contentsDigest);
    } catch (NoSuchFileException e) {
      // If the file doesn't exist, we need to create it.
      return true;
    } catch (NoSuchAlgorithmException e) {
      throw Throwables.propagate(e);
    }
  }

  /**
   * Looks for {@code executableToFind} under each entry of {@code pathsToSearch} and returns
   * the full path ({@code pathToSearch/executableToFind)}) to the first one which
   * exists on disk as an executable file.
   *
   * This is similar to the {@code which} command in Unix, but handles the various extensions
   * that are configured by Windows (when supplied with valid {@code extensions}).
   *
   * {@code executableToFind} must be a relative path.
   *
   * If none are found, returns {@link Optional#absent()}.
   */
  public static Optional<Path> searchPathsForExecutable(
      Path executableToFind,
      Collection<Path> pathsToSearch,
      Collection<String> extensions) {
    return searchPathsForExecutable(
        executableToFind,
        pathsToSearch,
        extensions,
        DEFAULT_PATH_IS_EXECUTABLE_CHECKER);
  }

  /**
   * Looks for {@code executableToFind} under each entry of {@code pathsToSearch} and returns
   * the full path ({@code pathToSearch/executableToFind)}) to the first one for which
   * {@code pathIsExecutableChecker(path)} returns true.
   *
   * This is similar to the {@code which} command in Unix, but handles the various extensions
   * that are configured by Windows (when supplied with valid {@code extensions}).
   *
   * {@code executableToFind} must be a relative path.
   *
   * If none are found, returns {@link Optional#absent()}.
   */
  public static Optional<Path> searchPathsForExecutable(
      Path executableToFind,
      Collection<Path> pathsToSearch,
      Collection<String> extensions,
      Function<Path, Boolean> pathIsExecutableChecker) {
    Preconditions.checkArgument(
        !executableToFind.isAbsolute(),
        "Path %s must be relative",
        executableToFind);

    for (Path pathToSearch : pathsToSearch) {
      Optional<Path> maybeResolved = resolveExecutable(
          pathToSearch,
          executableToFind,
          extensions,
          pathIsExecutableChecker);
      if (maybeResolved.isPresent()) {
        return maybeResolved;
      }
    }
    return Optional.absent();
  }

  private static Optional<Path> resolveExecutable(
      Path base,
      Path executableToFind,
      Collection<String> extensions,
      Function<Path, Boolean> pathIsExecutableChecker) {
    if (extensions.isEmpty()) {
      Path resolved = base.resolve(executableToFind);
      if (pathIsExecutableChecker.apply(resolved)) {
        return Optional.of(resolved);
      }
      return Optional.absent();
    }
    for (String pathExt : extensions) {
      Path resolved = base.resolve(executableToFind + pathExt);
      if (pathIsExecutableChecker.apply(resolved)) {
        return Optional.of(resolved);
      }
    }
    return Optional.absent();
  }

  private static byte[] inputStreamDigest(InputStream inputStream, MessageDigest messageDigest)
      throws IOException {
    try (DigestInputStream dis = new DigestInputStream(inputStream, messageDigest)) {
      byte[] buf = new byte[4096];
      while (true) {
        // Read the contents of the existing file so we can hash it.
        if (dis.read(buf) == -1) {
          break;
        }
      }
      return dis.getMessageDigest().digest();
    }
  }
}
