// Copyright (C) 2013 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.reviewdb.client;

import com.google.gerrit.common.UsedAt;

/** Constants and utilities for Gerrit-specific ref names. */
public class RefNames {
  public static final String HEAD = "HEAD";

  public static final String REFS = "refs/";

  public static final String REFS_HEADS = "refs/heads/";

  public static final String REFS_TAGS = "refs/tags/";

  public static final String REFS_CHANGES = "refs/changes/";

  public static final String REFS_META = "refs/meta/";

  /** Note tree listing commits we refuse {@code refs/meta/reject-commits} */
  public static final String REFS_REJECT_COMMITS = "refs/meta/reject-commits";

  /** Configuration settings for a project {@code refs/meta/config} */
  public static final String REFS_CONFIG = "refs/meta/config";

  /** Note tree listing external IDs */
  public static final String REFS_EXTERNAL_IDS = "refs/meta/external-ids";

  /** Magic user branch in All-Users {@code refs/users/self} */
  public static final String REFS_USERS_SELF = "refs/users/self";

  /** Default user preference settings */
  public static final String REFS_USERS_DEFAULT = RefNames.REFS_USERS + "default";

  /** Configurations of project-specific dashboards (canned search queries). */
  public static final String REFS_DASHBOARDS = "refs/meta/dashboards/";

  /** Sequence counters in NoteDb. */
  public static final String REFS_SEQUENCES = "refs/sequences/";

  /** NoteDb schema version number. */
  public static final String REFS_VERSION = "refs/meta/version";

  /**
   * Prefix applied to merge commit base nodes.
   *
   * <p>References in this directory should take the form {@code refs/cache-automerge/xx/yyyy...}
   * where xx is the first two digits of the merge commit's object name, and yyyyy... is the
   * remaining 38. The reference should point to a treeish that is the automatic merge result of the
   * merge commit's parents.
   */
  public static final String REFS_CACHE_AUTOMERGE = "refs/cache-automerge/";

  /** Suffix of a meta ref in the NoteDb. */
  public static final String META_SUFFIX = "/meta";

  /** Suffix of a ref that stores robot comments in the NoteDb. */
  public static final String ROBOT_COMMENTS_SUFFIX = "/robot-comments";

  public static final String EDIT_PREFIX = "edit-";

  /*
   * The following refs contain an account ID and should be visible only to that account.
   *
   * Parsing the account ID from the ref is implemented in Account.Id#fromRef(String). This ensures
   * that VisibleRefFilter hides those refs from other users.
   *
   * This applies to:
   * - User branches (e.g. 'refs/users/23/1011123')
   * - Draft comment refs (e.g. 'refs/draft-comments/73/67473/1011123')
   * - Starred changes refs (e.g. 'refs/starred-changes/73/67473/1011123')
   */

  /** Preference settings for a user {@code refs/users} */
  public static final String REFS_USERS = "refs/users/";

  /** NoteDb ref for a group {@code refs/groups} */
  public static final String REFS_GROUPS = "refs/groups/";

  /** NoteDb ref for the NoteMap of all group names */
  public static final String REFS_GROUPNAMES = "refs/meta/group-names";

  /**
   * NoteDb ref for deleted groups {@code refs/deleted-groups}. This ref namespace is foreseen as an
   * attic for deleted groups (it's reserved but not used yet)
   */
  public static final String REFS_DELETED_GROUPS = "refs/deleted-groups/";

  /** Draft inline comments of a user on a change */
  public static final String REFS_DRAFT_COMMENTS = "refs/draft-comments/";

  /** A change starred by a user */
  public static final String REFS_STARRED_CHANGES = "refs/starred-changes/";

  public static String fullName(String ref) {
    return (ref.startsWith(REFS) || ref.equals(HEAD)) ? ref : REFS_HEADS + ref;
  }

  public static final String shortName(String ref) {
    if (ref.startsWith(REFS_HEADS)) {
      return ref.substring(REFS_HEADS.length());
    } else if (ref.startsWith(REFS_TAGS)) {
      return ref.substring(REFS_TAGS.length());
    }
    return ref;
  }

  public static String changeMetaRef(Change.Id id) {
    StringBuilder r = newStringBuilder().append(REFS_CHANGES);
    return shard(id.get(), r).append(META_SUFFIX).toString();
  }

  public static String robotCommentsRef(Change.Id id) {
    StringBuilder r = newStringBuilder().append(REFS_CHANGES);
    return shard(id.get(), r).append(ROBOT_COMMENTS_SUFFIX).toString();
  }

  public static boolean isNoteDbMetaRef(String ref) {
    if (ref.startsWith(REFS_CHANGES)
        && (ref.endsWith(META_SUFFIX) || ref.endsWith(ROBOT_COMMENTS_SUFFIX))) {
      return true;
    }
    if (ref.startsWith(REFS_DRAFT_COMMENTS) || ref.startsWith(REFS_STARRED_CHANGES)) {
      return true;
    }
    return false;
  }

  /** True if the provided ref is in {@code refs/changes/*}. */
  public static boolean isRefsChanges(String ref) {
    return ref.startsWith(REFS_CHANGES);
  }

  public static String refsGroups(AccountGroup.UUID groupUuid) {
    return REFS_GROUPS + shardUuid(groupUuid.get());
  }

  public static String refsDeletedGroups(AccountGroup.UUID groupUuid) {
    return REFS_DELETED_GROUPS + shardUuid(groupUuid.get());
  }

  public static String refsUsers(Account.Id accountId) {
    StringBuilder r = newStringBuilder().append(REFS_USERS);
    return shard(accountId.get(), r).toString();
  }

  public static String refsDraftComments(Change.Id changeId, Account.Id accountId) {
    return buildRefsPrefix(REFS_DRAFT_COMMENTS, changeId.get()).append(accountId.get()).toString();
  }

  public static String refsDraftCommentsPrefix(Change.Id changeId) {
    return buildRefsPrefix(REFS_DRAFT_COMMENTS, changeId.get()).toString();
  }

  public static String refsStarredChanges(Change.Id changeId, Account.Id accountId) {
    return buildRefsPrefix(REFS_STARRED_CHANGES, changeId.get()).append(accountId.get()).toString();
  }

  public static String refsStarredChangesPrefix(Change.Id changeId) {
    return buildRefsPrefix(REFS_STARRED_CHANGES, changeId.get()).toString();
  }

  private static StringBuilder buildRefsPrefix(String prefix, int id) {
    StringBuilder r = newStringBuilder().append(prefix);
    return shard(id, r).append('/');
  }

  public static String refsCacheAutomerge(String hash) {
    return REFS_CACHE_AUTOMERGE + hash.substring(0, 2) + '/' + hash.substring(2);
  }

  public static String shard(int id) {
    if (id < 0) {
      return null;
    }
    return shard(id, newStringBuilder()).toString();
  }

  private static StringBuilder shard(int id, StringBuilder sb) {
    int n = id % 100;
    if (n < 10) {
      sb.append('0');
    }
    sb.append(n);
    sb.append('/');
    sb.append(id);
    return sb;
  }

  @UsedAt(UsedAt.Project.PLUGINS_ALL)
  public static String shardUuid(String uuid) {
    if (uuid == null || uuid.length() < 2) {
      throw new IllegalArgumentException("UUIDs must consist of at least two characters");
    }
    return uuid.substring(0, 2) + '/' + uuid;
  }

  /**
   * Returns reference for this change edit with sharded user and change number:
   * refs/users/UU/UUUU/edit-CCCC/P.
   *
   * @param accountId account id
   * @param changeId change number
   * @param psId patch set number
   * @return reference for this change edit
   */
  public static String refsEdit(Account.Id accountId, Change.Id changeId, PatchSet.Id psId) {
    return refsEditPrefix(accountId, changeId) + psId.get();
  }

  /**
   * Returns reference prefix for this change edit with sharded user and change number:
   * refs/users/UU/UUUU/edit-CCCC/.
   *
   * @param accountId account id
   * @param changeId change number
   * @return reference prefix for this change edit
   */
  public static String refsEditPrefix(Account.Id accountId, Change.Id changeId) {
    return refsEditPrefix(accountId) + changeId.get() + '/';
  }

  public static String refsEditPrefix(Account.Id accountId) {
    return refsUsers(accountId) + '/' + EDIT_PREFIX;
  }

  public static boolean isRefsEdit(String ref) {
    return ref != null && ref.startsWith(REFS_USERS) && ref.contains(EDIT_PREFIX);
  }

  public static boolean isRefsUsers(String ref) {
    return ref.startsWith(REFS_USERS);
  }

  /**
   * Whether the ref is a group branch that stores NoteDb data of a group. Returns {@code true} for
   * all refs that start with {@code refs/groups/}.
   */
  public static boolean isRefsGroups(String ref) {
    return ref.startsWith(REFS_GROUPS);
  }

  /**
   * Whether the ref is a group branch that stores NoteDb data of a deleted group. Returns {@code
   * true} for all refs that start with {@code refs/deleted-groups/}.
   */
  public static boolean isRefsDeletedGroups(String ref) {
    return ref.startsWith(REFS_DELETED_GROUPS);
  }

  /**
   * Whether the ref is used for storing group data in NoteDb. Returns {@code true} for all group
   * branches, refs/meta/group-names and deleted group branches.
   */
  public static boolean isGroupRef(String ref) {
    return isRefsGroups(ref) || isRefsDeletedGroups(ref) || REFS_GROUPNAMES.equals(ref);
  }

  /** Whether the ref is the configuration branch, i.e. {@code refs/meta/config}, for a project. */
  public static boolean isConfigRef(String ref) {
    return REFS_CONFIG.equals(ref);
  }

  /**
   * Whether the ref is managed by Gerrit. Covers all Gerrit-internal refs like refs/cache-automerge
   * and refs/meta as well as refs/changes. Does not cover user-created refs like branches or custom
   * ref namespaces like refs/my-company.
   */
  public static boolean isGerritRef(String ref) {
    return ref.startsWith(REFS_CHANGES)
        || ref.startsWith(REFS_META)
        || ref.startsWith(REFS_CACHE_AUTOMERGE)
        || ref.startsWith(REFS_DRAFT_COMMENTS)
        || ref.startsWith(REFS_DELETED_GROUPS)
        || ref.startsWith(REFS_SEQUENCES)
        || ref.startsWith(REFS_GROUPS)
        || ref.startsWith(REFS_GROUPNAMES)
        || ref.startsWith(REFS_USERS)
        || ref.startsWith(REFS_STARRED_CHANGES);
  }

  static Integer parseShardedRefPart(String name) {
    if (name == null) {
      return null;
    }

    String[] parts = name.split("/");
    int n = parts.length;
    if (n < 2) {
      return null;
    }

    // Last 2 digits.
    int le;
    for (le = 0; le < parts[0].length(); le++) {
      if (!Character.isDigit(parts[0].charAt(le))) {
        return null;
      }
    }
    if (le != 2) {
      return null;
    }

    // Full ID.
    int ie;
    for (ie = 0; ie < parts[1].length(); ie++) {
      if (!Character.isDigit(parts[1].charAt(ie))) {
        if (ie == 0) {
          return null;
        }
        break;
      }
    }

    int shard = Integer.parseInt(parts[0]);
    int id = Integer.parseInt(parts[1].substring(0, ie));

    if (id % 100 != shard) {
      return null;
    }
    return id;
  }

  @UsedAt(UsedAt.Project.PLUGINS_ALL)
  public static String parseShardedUuidFromRefPart(String name) {
    if (name == null) {
      return null;
    }

    String[] parts = name.split("/");
    int n = parts.length;
    if (n != 2) {
      return null;
    }

    // First 2 chars.
    if (parts[0].length() != 2) {
      return null;
    }

    // Full UUID.
    String uuid = parts[1];
    if (!uuid.startsWith(parts[0])) {
      return null;
    }

    return uuid;
  }

  /**
   * Skips a sharded ref part at the beginning of the name.
   *
   * <p>E.g.: "01/1" -> "", "01/1/" -> "/", "01/1/2" -> "/2", "01/1-edit" -> "-edit"
   *
   * @param name ref part name
   * @return the rest of the name, {@code null} if the ref name part doesn't start with a valid
   *     sharded ID
   */
  static String skipShardedRefPart(String name) {
    if (name == null) {
      return null;
    }

    String[] parts = name.split("/");
    int n = parts.length;
    if (n < 2) {
      return null;
    }

    // Last 2 digits.
    int le;
    for (le = 0; le < parts[0].length(); le++) {
      if (!Character.isDigit(parts[0].charAt(le))) {
        return null;
      }
    }
    if (le != 2) {
      return null;
    }

    // Full ID.
    int ie;
    for (ie = 0; ie < parts[1].length(); ie++) {
      if (!Character.isDigit(parts[1].charAt(ie))) {
        if (ie == 0) {
          return null;
        }
        break;
      }
    }

    int shard = Integer.parseInt(parts[0]);
    int id = Integer.parseInt(parts[1].substring(0, ie));

    if (id % 100 != shard) {
      return null;
    }

    return name.substring(2 + 1 + ie); // 2 for the length of the shard, 1 for the '/'
  }

  /**
   * Parses an ID that follows a sharded ref part at the beginning of the name.
   *
   * <p>E.g.: "01/1/2" -> 2, "01/1/2/4" -> 2, ""01/1/2-edit" -> 2
   *
   * @param name ref part name
   * @return ID that follows the sharded ref part at the beginning of the name, {@code null} if the
   *     ref name part doesn't start with a valid sharded ID or if no valid ID follows the sharded
   *     ref part
   */
  static Integer parseAfterShardedRefPart(String name) {
    String rest = skipShardedRefPart(name);
    if (rest == null || !rest.startsWith("/")) {
      return null;
    }

    rest = rest.substring(1);

    int ie;
    for (ie = 0; ie < rest.length(); ie++) {
      if (!Character.isDigit(rest.charAt(ie))) {
        break;
      }
    }
    if (ie == 0) {
      return null;
    }
    return Integer.parseInt(rest.substring(0, ie));
  }

  static Integer parseRefSuffix(String name) {
    if (name == null) {
      return null;
    }
    int i = name.length();
    while (i > 0) {
      char c = name.charAt(i - 1);
      if (c == '/') {
        break;
      } else if (!Character.isDigit(c)) {
        return null;
      }
      i--;
    }
    if (i == 0) {
      return null;
    }
    return Integer.valueOf(name.substring(i));
  }

  private static StringBuilder newStringBuilder() {
    // Many refname types in this file are always are longer than the default of 16 chars, so
    // presize StringBuilders larger by default. This hurts readability less than accurate
    // calculations would, at a negligible cost to memory overhead.
    return new StringBuilder(64);
  }

  private RefNames() {}
}
