// Copyright 2018 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.vfs;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import com.google.devtools.build.lib.util.TestType;
import com.google.devtools.build.lib.vfs.DigestHashFunction.DigestLength.DigestLengthImpl;
import com.google.devtools.common.options.Converter;
import com.google.devtools.common.options.OptionsParsingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;

/**
 * Type of hash function to use for digesting files.
 *
 * <p>This tracks parallel {@link java.security.MessageDigest} and {@link HashFunction} interfaces
 * for each provided hash, as Bazel uses both - MessageDigest where performance is critical and
 * HashFunctions where ease-of-use wins over.
 */
// The underlying HashFunctions are immutable and thread safe.
public class DigestHashFunction {
  // This map must be declared first to make sure that calls to register() have it ready.
  private static final HashMap<String, DigestHashFunction> hashFunctionRegistry = new HashMap<>();

  /** Describes the length of a digest. */
  public interface DigestLength {
    /** Returns the length of a digest by inspecting its bytes. Used for variable-length digests. */
    default int getDigestLength(byte[] bytes, int offset) {
      return getDigestMaximumLength();
    }

    /** Returns the maximum length a digest can turn into. */
    int getDigestMaximumLength();

    /** Default implementation that simply returns a fixed length. */
    class DigestLengthImpl implements DigestLength {
      private final int length;

      DigestLengthImpl(HashFunction hashFunction) {
        this.length = hashFunction.bits() / 8;
      }

      @Override
      public int getDigestMaximumLength() {
        return length;
      }
    }
  }

  public static final DigestHashFunction SHA1 = register(Hashing.sha1(), "SHA-1", "SHA1");
  public static final DigestHashFunction SHA256 = register(Hashing.sha256(), "SHA-256", "SHA256");

  private static DigestHashFunction defaultHash;

  private final HashFunction hashFunction;
  private final DigestLength digestLength;
  private final String name;
  private final MessageDigest messageDigestPrototype;
  private final boolean messageDigestPrototypeSupportsClone;
  private final ImmutableList<String> names;

  private DigestHashFunction(
      HashFunction hashFunction, DigestLength digestLength, ImmutableList<String> names) {
    this.hashFunction = hashFunction;
    this.digestLength = digestLength;
    checkArgument(!names.isEmpty());
    this.name = names.get(0);
    this.names = names;
    this.messageDigestPrototype = getMessageDigestInstance();
    this.messageDigestPrototypeSupportsClone = supportsClone(messageDigestPrototype);
  }

  public static DigestHashFunction register(
      HashFunction hash, String hashName, String... altNames) {
    return register(hash, new DigestLengthImpl(hash), hashName, altNames);
  }

  /**
   * Creates a new DigestHashFunction that is registered to be recognized by its name in {@link
   * DigestFunctionConverter}.
   *
   * @param hashName the canonical name for this hash function - and the name that can be used to
   *     uncover the MessageDigest.
   * @param altNames alternative names that will be mapped to this function by the converter but
   *     will not serve as the canonical name for the DigestHashFunction.
   * @param hash The {@link HashFunction} to register.
   * @throws IllegalArgumentException if the name is already registered.
   */
  public static DigestHashFunction register(
      HashFunction hash, DigestLength digestLength, String hashName, String... altNames) {
    try {
      MessageDigest.getInstance(hashName);
    } catch (NoSuchAlgorithmException e) {
      throw new IllegalArgumentException(
          "The hash function name provided does not correspond to a valid MessageDigest: "
              + hashName,
          e);
    }

    ImmutableList<String> names =
        ImmutableList.<String>builder().add(hashName).add(altNames).build();
    DigestHashFunction hashFunction = new DigestHashFunction(hash, digestLength, names);
    synchronized (hashFunctionRegistry) {
      for (String name : names) {
        if (hashFunctionRegistry.containsKey(name)) {
          throw new IllegalArgumentException("Hash function " + name + " is already registered.");
        }
        hashFunctionRegistry.put(name, hashFunction);
      }
    }
    return hashFunction;
  }

  /**
   * Returns the default DigestHashFunction for this instance of Bazel.
   *
   * <p>Note: This is a synchronized function, to make sure it does not occur concurrently with
   * {@link #setDefault(DigestHashFunction)}. Once this value is set, it's a constant, so to prevent
   * blocking calls, users should cache this value if needed.
   *
   * @throws DefaultHashFunctionNotSetException if the default has not yet been set by a previous
   *     call to {@link #setDefault}.
   */
  public static synchronized DigestHashFunction getDefault()
      throws DefaultHashFunctionNotSetException {
    DigestHashFunction hash = defaultHash;
    if (hash == null) {
      throw new DefaultHashFunctionNotSetException("DigestHashFunction default has not been set");
    }
    return hash;
  }

  /**
   * Returns the default DigestHashFunction, or the testing default if unset.
   */
  public static DigestHashFunction getDefaultUnchecked() {
    try {
      return getDefault();
    } catch (DefaultHashFunctionNotSetException e) {
      // Some tests use this class without calling GoogleUnixFileSystemModule.globalInit().
      Preconditions.checkState(TestType.isInTest(), "Default hash function has not been set");
      return DigestHashFunction.SHA256;
    }
  }


  /** Indicates that the default has not been initialized. */
  public static final class DefaultHashFunctionNotSetException extends Exception {
    DefaultHashFunctionNotSetException(String message) {
      super(message);
    }
  }

  /**
   * Sets the default DigestHashFunction for this instance of Bazel - can only be set once to
   * prevent incongruities.
   *
   * @throws DefaultAlreadySetException if it was already set.
   */
  public static synchronized void setDefault(DigestHashFunction hash)
      throws DefaultAlreadySetException {
    Preconditions.checkNotNull(hash);
    // Permit redundant calls.  This is difficult to avoid with test suites.
    if (defaultHash == null || defaultHash == hash) {
      defaultHash = hash;
      return;
    }
    throw new DefaultAlreadySetException(
        String.format(
            "setDefault(%s) failed. The default has already been set to %s, you cannot change it.",
            hash.name, defaultHash.name));
  }

  /** Failure to set the default if the default already being set. */
  public static final class DefaultAlreadySetException extends Exception {
    DefaultAlreadySetException(String message) {
      super(message);
    }
  }

  /** Converts a string to its registered {@link DigestHashFunction}. */
  public static class DigestFunctionConverter implements Converter<DigestHashFunction> {
    @Override
    public DigestHashFunction convert(String input) throws OptionsParsingException {
      for (Entry<String, DigestHashFunction> possibleFunctions : hashFunctionRegistry.entrySet()) {
        if (possibleFunctions.getKey().equalsIgnoreCase(input)) {
          return possibleFunctions.getValue();
        }
      }
      throw new OptionsParsingException("Not a valid hash function.");
    }

    @Override
    public String getTypeDescription() {
      return "hash function";
    }
  }

  public HashFunction getHashFunction() {
    return hashFunction;
  }

  public MessageDigest cloneOrCreateMessageDigest() {
    if (messageDigestPrototypeSupportsClone) {
      try {
        return (MessageDigest) messageDigestPrototype.clone();
      } catch (CloneNotSupportedException e) {
        // We checked at initialization that this could be cloned, so this should never happen.
        throw new IllegalStateException("Could not clone message digest", e);
      }
    } else {
      return getMessageDigestInstance();
    }
  }

  public DigestLength getDigestLength() {
    return digestLength;
  }

  public ImmutableList<String> getNames() {
    return names;
  }

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

  private MessageDigest getMessageDigestInstance() {
    try {
      return MessageDigest.getInstance(name);
    } catch (NoSuchAlgorithmException e) {
      // We check when we register() this digest function that the message digest exists. This
      // should never happen.
      throw new IllegalStateException("message digest " + name + " not available", e);
    }
  }

  private static boolean supportsClone(MessageDigest toCheck) {
    try {
      toCheck.clone();
      return true;
    } catch (CloneNotSupportedException e) {
      return false;
    }
  }

  @VisibleForTesting
  static Collection<DigestHashFunction> getPossibleHashFunctions() {
    return hashFunctionRegistry.values();
  }
}
