// Copyright (C) 2017 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.googlesource.gerrit.plugins.events.fsstore;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;

/** Some Filesystem utilities */
public class Fs {
  /** Try to create a link. Do NOT throw IOExceptions. */
  public static boolean tryCreateLink(Path link, Path existing) {
    try {
      Files.createLink(link, existing);
      return true;
    } catch (IOException e) {
      return false;
    }
  }

  /** Try to move a file/dir atomically. Do NOT throw IOExceptions. */
  public static boolean tryAtomicMove(Path src, Path dst) {
    try {
      Files.move(src, dst, StandardCopyOption.ATOMIC_MOVE);
      return true;
    } catch (IOException e) {
      return false;
    }
  }

  /** Try to recursively delete a dir. Do NOT throw IOExceptions. */
  public static boolean tryRecursiveDelete(Path dir) {
    try {
      Files.walkFileTree(
          dir,
          new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
                throws IOException {
              tryDelete(file);
              return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException e) throws IOException {
              tryDelete(dir);
              return FileVisitResult.CONTINUE;
            }
          });
    } catch (IOException e) { // Intent of 'try' function is to ignore these.
    }
    return !Files.exists(dir);
  }

  /**
   * Try to recursively delete entries, up to max count, in a dir older than expiry. Do NOT throw
   * IOExceptions.
   *
   * @return whether all entries were deleted
   */
  public static boolean tryRecursiveDeleteEntriesOlderThan(Path dir, FileTime expiry, int max) {
    try (DirectoryStream<Path> dirEntries = Files.newDirectoryStream(dir)) {
      for (Path path : dirEntries) {
        if (isOlderThan(path, expiry)) {
          if (max-- < 1) {
            return false;
          }
          tryRecursiveDelete(path);
        }
      }
    } catch (IOException e) { // Intent of 'try' function is to ignore these.
    }
    return true;
  }

  /** Are all entries in a directory tree older than expiry? Do NOT throw IOExceptions. */
  public static boolean isAllEntriesOlderThan(Path dir, FileTime expiry) {
    if (!isOlderThan(dir, expiry)) {
      return false;
    }
    try (DirectoryStream<Path> dirEntries = Files.newDirectoryStream(dir)) {
      for (Path path : dirEntries) {
        if (!isAllEntriesOlderThan(path, expiry)) {
          return false;
        }
      }
    } catch (NotDirectoryException e) { // can't recurse if not a directory
    } catch (IOException e) {
      return false; // Modified after start, so not older
    }
    return true;
  }

  /** Is an entry older than expiry. Do NOT throw IOExceptions. */
  public static boolean isOlderThan(Path path, FileTime expiry) {
    try {
      return expiry.compareTo(Files.getLastModifiedTime(path)) > 0;
    } catch (IOException e) {
      return false;
    }
  }

  /** Try to delete a path. Do NOT throw IOExceptions. */
  public static void tryDelete(Path path) {
    try {
      Files.delete(path);
    } catch (IOException e) { // Intent of 'try' function is to ignore these.
    }
  }

  /** Try to delete a dir and it parents (like rmdir -p). Do NOT throw IOExceptions. */
  public static void unsafeRecursiveRmdir(File dir) {
    try {
      while (unsafeRmdir(dir)) {
        dir = dir.getParentFile();
      }
    } catch (IOException e) { // Intent of 'try' function is to ignore these.
    }
  }

  /**
   * Try to delete a dir and it parents (like rmdir -p). Do NOT throw IOExceptions. Unsafe since the
   * directory check and removal are not atomic.
   */
  public static boolean unsafeRmdir(File dir) throws IOException {
    if (!dir.isDirectory()) {
      throw new IOException(dir + " not a directory");
    }
    return dir.delete();
  }

  /** Read the contents of a UTF_8 encoded file as a String */
  public static String readUtf8(Path file) throws IOException {
    StringBuffer buffer = new StringBuffer();
    for (String line : Files.readAllLines(file, StandardCharsets.UTF_8)) {
      buffer.append(line);
    }
    return buffer.toString();
  }

  /** Write the contents of a String as a UTF_8 encoded file */
  public static void writeUtf8(Path file, String s) throws IOException {
    Files.write(file, s.getBytes(StandardCharsets.UTF_8));
  }

  /** Get the first entry in a directory. */
  public static Path getFirstDirEntry(Path dir) throws IOException {
    try (DirectoryStream<Path> dirEntries = Files.newDirectoryStream(dir)) {
      Iterator<Path> it = dirEntries.iterator();
      return it.hasNext() ? it.next() : null;
    }
  }

  /**
   * A drop in replacement for Files.createDirectories that works even when the tail of `path` is a
   * link.
   */
  public static Path createDirectories(Path path) throws IOException {
    try {
      return Files.createDirectories(path);
    } catch (FileAlreadyExistsException e) {
      return Files.createDirectories(Files.readSymbolicLink(path));
    }
  }

  /** Get the reparented path as if a path were moved to a new location */
  public static Path reparent(Path src, Path dst) {
    return dst.resolve(basename(src));
  }

  /** Get the tail of a path (similar to the unix basename command) */
  public static Path basename(Path p) {
    return p.getName(p.getNameCount() - 1);
  }

  /** Get a FileTime indicating a certain amount of time beforehand (ago). */
  public static FileTime getFileTimeAgo(long ago, TimeUnit unit) {
    long ms = TimeUnit.MILLISECONDS.convert(ago, unit);
    return FileTime.fromMillis(System.currentTimeMillis() - ms);
  }
}
