// Copyright (C) 2019 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.google.gerrit.plugins.checks;

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

import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.hash.Hashing;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.RefNames;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;

/**
 * UUID of a checker.
 *
 * <p>UUIDs are of the form {@code SCHEME ':' ID}, where:
 *
 * <ul>
 *   <li>The allowed characters within either part are {@code [a-zA-Z0-9._-]}.
 *   <li>Scheme is a short string that, by convention, is associated with the external system that
 *       created the checker (e.g. {@code jenkins}).
 *   <li>Scheme must be valid as a ref name component according to {@code git-check-ref-format}.
 *   <li>Scheme has a low length limit (100 chars), to ensure it can be used as part of a refname
 *       under all possible ref storage systems.
 *   <li>ID is an arbitrary string provided by the external system.
 * </ul>
 */
@AutoValue
public abstract class CheckerUuid implements Comparable<CheckerUuid> {
  @VisibleForTesting static final int MAX_SCHEME_LENGTH = 100;

  private static final Pattern UUID_PATTERN;

  static {
    // The set of allowed characters is somewhat arbitrarily small and may be expanded in the future
    // if there is a concrete use case. Some considerations:
    //  * It's nice for UUIDs to be URL-safe.
    //  * UUIDs are currently stored one per line in the CheckersByRepositoryNotes format, so
    //    newlines would be problematic.
    //  * UUIDs are stored in git config values.
    String part = "[a-zA-Z0-9._-]+";
    UUID_PATTERN = Pattern.compile(String.format("^(?<scheme>%s):(?<id>%s)$", part, part));
  }

  /**
   * Attempts to parse the given UUID string into a {@code CheckerUuid}.
   *
   * @param uuid UUID string.
   * @return new UUID if {@code uuid} is a valid UUID, or empty otherwise.
   */
  public static Optional<CheckerUuid> tryParse(@Nullable String uuid) {
    if (uuid == null) {
      return Optional.empty();
    }
    Matcher m = UUID_PATTERN.matcher(uuid);
    if (!m.find()) {
      return Optional.empty();
    }
    String scheme = m.group("scheme");
    if (scheme.length() > MAX_SCHEME_LENGTH) {
      return Optional.empty();
    }
    // git-check-ref-format(1) says:
    // "no slash-separated component can begin with a dot `.` or end with the sequence `.lock`."
    // But JGit's isValidRefName doesn't currently enforce the .lock constraint.
    if (scheme.endsWith(Constants.LOCK_SUFFIX)) {
      return Optional.empty();
    }
    if (!Repository.isValidRefName(toRefName(scheme, "x"))) {
      return Optional.empty();
    }
    return Optional.of(new AutoValue_CheckerUuid(scheme, m.group("id")));
  }

  private static String toRefName(String scheme, String hashedId) {
    return CheckerRef.REFS_CHECKERS + scheme + '/' + hashedId;
  }

  /**
   * Returns whether the given input is a valid UUID string.
   *
   * @param uuid UUID string.
   * @return true if {@code uuid} is a valid UUID, false otherwise.
   */
  public static boolean isUuid(@Nullable String uuid) {
    return tryParse(uuid).isPresent();
  }

  /**
   * Parses the given UUID string into a {@code CheckerUuid}, throwing an unchecked exception if it
   * is not in the proper format.
   *
   * @param uuid UUID string.
   * @return new UUID.
   */
  public static CheckerUuid parse(String uuid) {
    return tryParse(uuid)
        .orElseThrow(() -> new IllegalArgumentException("invalid checker UUID: " + uuid));
  }

  /**
   * Scheme portion of the UUID.
   *
   * @return the scheme.
   */
  public abstract String scheme();

  /**
   * ID portion of the UUID.
   *
   * @return the ID.
   */
  public abstract String id();

  /**
   * Computes the name for this checker's config ref.
   *
   * <p>Ref names are of the form {@code 'refs/checkers/' SCHEME '/' SHARD(SHA1(ID))}.
   *
   * @return hex SHA-1 of this UUID's string representation.
   */
  @SuppressWarnings("deprecation") // SHA-1 used where Git object IDs are required.
  public String toRefName() {
    return toRefName(
        scheme(), RefNames.shardUuid(Hashing.sha1().hashString(id(), UTF_8).toString()));
  }

  public String get() {
    return scheme() + ":" + id();
  }

  @Override
  public final String toString() {
    return get();
  }

  @Override
  public final int compareTo(CheckerUuid o) {
    return get().compareTo(o.get());
  }
}
