// Copyright 2016 The Bazel Authors. All rights reserved.
//
// 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.google.devtools.build.lib.bazel.repository.cache;

import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hasher;
import com.google.common.hash.Hashing;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import javax.annotation.Nullable;

/** The cache implementation to store download artifacts from external repositories.
 *  TODO(jingwen): Implement file locking for concurrent cache accesses.
 */
public class RepositoryCache {

  /** The types of cache keys used. */
  public enum KeyType {
    SHA1("SHA-1", "\\p{XDigit}{40}", "sha1", Hashing.sha1()),
    SHA256("SHA-256", "\\p{XDigit}{64}", "sha256", Hashing.sha256()),
    SHA384("SHA-384", "\\p{XDigit}{96}", "sha384", Hashing.sha384()),
    SHA512("SHA-512", "\\p{XDigit}{128}", "sha512", Hashing.sha512());

    private final String stringRepr;
    private final String regexp;
    private final String hashName;
    @SuppressWarnings("ImmutableEnumChecker")
    private final HashFunction hashFunction;

    KeyType(String stringRepr, String regexp, String hashName, HashFunction hashFunction) {
      this.stringRepr = stringRepr;
      this.regexp = regexp;
      this.hashName = hashName;
      this.hashFunction = hashFunction;
    }

    public boolean isValid(@Nullable String checksum) {
      return !Strings.isNullOrEmpty(checksum) && checksum.matches(regexp);
    }

    public Path getCachePath(Path parentDirectory) {
      return parentDirectory.getChild(hashName);
    }

    public Hasher newHasher() {
      return hashFunction.newHasher();
    }

    public String getHashName() {
      return hashName;
    }

    @Override
    public String toString() {
      return stringRepr;
    }
  }

  private static final int BUFFER_SIZE = 32 * 1024;

  // Repository cache subdirectories
  private static final String CAS_DIR = "content_addressable";

  // Rename cached files to this value to simplify lookup.
  public static final String DEFAULT_CACHE_FILENAME = "file";
  public static final String TMP_PREFIX = "tmp-";
  public static final String ID_PREFIX = "id-";

  @Nullable private Path repositoryCachePath;
  @Nullable private Path contentAddressablePath;
  private boolean useHardlinks;

  public void setRepositoryCachePath(@Nullable Path repositoryCachePath) {
    this.repositoryCachePath = repositoryCachePath;
    this.contentAddressablePath = (repositoryCachePath != null)
        ? repositoryCachePath.getRelative(CAS_DIR) : null;
  }

  public void setHardlink(boolean useHardlinks) {
    this.useHardlinks = useHardlinks;
  }

  /**
   * @return true iff the cache path is set.
   */
  public boolean isEnabled() {
    return repositoryCachePath != null;
  }

  /**
   * Determine if a cache entry exist, given a cache key.
   *
   * @param cacheKey The string key to cache the value by.
   * @param keyType The type of key used. See: KeyType
   * @return true if the cache entry exist, false otherwise.
   */
  public boolean exists(String cacheKey, KeyType keyType) {
    Preconditions.checkState(isEnabled());
    return keyType
        .getCachePath(contentAddressablePath)
        .getChild(cacheKey)
        .getChild(DEFAULT_CACHE_FILENAME)
        .exists();
  }

  boolean hasCanonicalId(String cacheKey, KeyType keyType, String canonicalId) {
    Preconditions.checkState(isEnabled());
    String idHash = keyType.newHasher().putString(canonicalId, UTF_8).hash().toString();
    return keyType
        .getCachePath(contentAddressablePath)
        .getChild(cacheKey)
        .getChild(ID_PREFIX + idHash)
        .exists();
  }

  public synchronized Path get(String cacheKey, Path targetPath, KeyType keyType)
      throws IOException, InterruptedException {
    return get(cacheKey, targetPath, keyType, null);
  }

  /**
   * Copy or hardlink cached value to a specified directory, if it exists.
   *
   * <p>We're using hardlinking instead of symlinking because symlinking require weird checks to
   * verify that the symlink still points to an existing artifact. e.g. cleaning up the central
   * cache but not the workspace cache.
   *
   * @param cacheKey The string key to cache the value by.
   * @param targetPath The path where the cache value should be copied to.
   * @param keyType The type of key used. See: KeyType
   * @param canonicalId If set to a non-empty string, restrict cache hits to those cases, where the
   *     entry with the given cacheKey was added with this String given.
   * @return The Path value where the cache value has been copied to. If cache value does not exist,
   *     return null.
   * @throws IOException
   */
  @Nullable
  public synchronized Path get(
      String cacheKey, Path targetPath, KeyType keyType, String canonicalId)
      throws IOException, InterruptedException {
    if (Thread.interrupted()) {
      throw new InterruptedException();
    }
    Preconditions.checkState(isEnabled());

    assertKeyIsValid(cacheKey, keyType);
    if (!exists(cacheKey, keyType)) {
      return null;
    }

    Path cacheEntry = keyType.getCachePath(contentAddressablePath).getRelative(cacheKey);
    Path cacheValue = cacheEntry.getRelative(DEFAULT_CACHE_FILENAME);

    try {
      assertFileChecksum(cacheKey, cacheValue, keyType);
    } catch (IOException e) {
      // New lines because this error message gets large printing multiple absolute filepaths.
      throw new IOException(e.getMessage() + "\n\n"
          + "Please delete the directory " + cacheEntry + " and try again.");
    }

    if (!Strings.isNullOrEmpty(canonicalId)) {
      if (!hasCanonicalId(cacheKey, keyType, canonicalId)) {
        return null;
      }
    }

    FileSystemUtils.createDirectoryAndParents(targetPath.getParentDirectory());
    if (useHardlinks) {
      FileSystemUtils.createHardLink(targetPath, cacheValue);
    } else {
      FileSystemUtils.copyFile(cacheValue, targetPath);
    }

    try {
      FileSystemUtils.touchFile(cacheValue);
    } catch (IOException e) {
      // Ignore, because the cache might be on a read-only volume.
    }

    return targetPath;
  }

  public synchronized void put(String cacheKey, Path sourcePath, KeyType keyType)
      throws IOException, InterruptedException {
    put(cacheKey, sourcePath, keyType, null);
  }

  /**
   * Copies a value from a specified path into the cache.
   *
   * @param cacheKey The string key to cache the value by.
   * @param sourcePath The path of the value to be cached.
   * @param keyType The type of key used. See: KeyType
   * @param canonicalId If set to a non-empty String associate the file with this name, allowing
   *     restricted cache lookups later.
   * @throws IOException
   */
  public synchronized void put(
      String cacheKey, Path sourcePath, KeyType keyType, String canonicalId)
      throws IOException, InterruptedException {
    // Check for interrupts while waiting for the monitor of this synchronized method
    if (Thread.interrupted()) {
      throw new InterruptedException();
    }
    Preconditions.checkState(isEnabled());

    assertKeyIsValid(cacheKey, keyType);
    ensureCacheDirectoryExists(keyType);

    Path cacheEntry = keyType.getCachePath(contentAddressablePath).getRelative(cacheKey);
    Path cacheValue = cacheEntry.getRelative(DEFAULT_CACHE_FILENAME);
    Path tmpName = cacheEntry.getRelative(TMP_PREFIX + UUID.randomUUID());
    FileSystemUtils.createDirectoryAndParents(cacheEntry);
    FileSystemUtils.copyFile(sourcePath, tmpName);
    FileSystemUtils.moveFile(tmpName, cacheValue);

    if (!Strings.isNullOrEmpty(canonicalId)) {
      byte[] canonicalIdBytes = canonicalId.getBytes(UTF_8);
      String idHash = keyType.newHasher().putBytes(canonicalIdBytes).hash().toString();
      OutputStream idStream = cacheEntry.getRelative(ID_PREFIX + idHash).getOutputStream();
      idStream.write(canonicalIdBytes);
      idStream.close();
    }
  }

  public synchronized String put(Path sourcePath, KeyType keyType)
      throws IOException, InterruptedException {
    return put(sourcePath, keyType, null);
  }

  /**
   * Copies a value from a specified path into the cache, computing the cache key itself.
   *
   * @param sourcePath The path of the value to be cached.
   * @param keyType The type of key to be used.
   * @param canonicalId If set to a non-empty String associate the file with this name, allowing
   *     restricted cache lookups later.
   * @throws IOException
   * @return The key for the cached entry.
   */
  public synchronized String put(Path sourcePath, KeyType keyType, String canonicalId)
      throws IOException, InterruptedException {
    String cacheKey = getChecksum(keyType, sourcePath);
    put(cacheKey, sourcePath, keyType, canonicalId);
    return cacheKey;
  }

  private void ensureCacheDirectoryExists(KeyType keyType) throws IOException {
    Path directoryPath = keyType.getCachePath(contentAddressablePath);
    if (!directoryPath.exists()) {
      FileSystemUtils.createDirectoryAndParents(directoryPath);
    }
  }

  /**
   * Assert that a file has an expected checksum.
   *
   * @param expectedChecksum The expected checksum of the file.
   * @param filePath The path to the file.
   * @param keyType The type of hash function. e.g. SHA-1, SHA-256
   * @throws IOException If the checksum does not match or the file cannot be hashed, an exception
   *     is thrown.
   */
  public static void assertFileChecksum(String expectedChecksum, Path filePath, KeyType keyType)
      throws IOException, InterruptedException {
    Preconditions.checkArgument(!expectedChecksum.isEmpty());

    String actualChecksum;
    try {
      actualChecksum = getChecksum(keyType, filePath);
    } catch (IOException e) {
      throw new IOException(
          "Could not hash file " + filePath + ": " + e.getMessage() + ", expected " + keyType
          + " of " + expectedChecksum + ". ");
    }
    if (!actualChecksum.equalsIgnoreCase(expectedChecksum)) {
      throw new IOException(
          "Downloaded file at " + filePath + " has " + keyType + " of " + actualChecksum
              + ", does not match expected " + keyType + " (" + expectedChecksum + ")");
    }
  }

  /**
   * Obtain the checksum of a file.
   *
   * @param keyType The type of hash function. e.g. SHA-1, SHA-256.
   * @param path The path to the file.
   * @throws IOException
   */
  public static String getChecksum(KeyType keyType, Path path)
      throws IOException, InterruptedException {
    Hasher hasher = keyType.newHasher();
    byte[] byteBuffer = new byte[BUFFER_SIZE];
    try (InputStream stream = path.getInputStream()) {
      int numBytesRead = stream.read(byteBuffer);
      while (numBytesRead != -1) {
        if (numBytesRead != 0) {
          // If more than 0 bytes were read, add them to the hash.
          hasher.putBytes(byteBuffer, 0, numBytesRead);
        }
        if (Thread.interrupted()) {
          throw new InterruptedException();
        }
        numBytesRead = stream.read(byteBuffer);
      }
    }
    return hasher.hash().toString();
  }

  private void assertKeyIsValid(String key, KeyType keyType) throws IOException {
    if (!keyType.isValid(key)) {
      throw new IOException("Invalid key \"" + key + "\" of type " + keyType + ". ");
    }
  }

  public Path getRootPath() {
    return repositoryCachePath;
  }

  public Path getContentAddressableCachePath() {
    return contentAddressablePath;
  }
}
