// 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.google.gerrit.server.group.db;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.InternalGroup;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.git.meta.VersionedMetaData;
import com.google.gerrit.server.util.time.TimeUtil;
import java.io.IOException;
import java.time.Instant;
import java.util.Arrays;
import java.util.Date;
import java.util.Optional;
import java.util.function.Function;
import java.util.regex.Pattern;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;

/**
 * A representation of a group in NoteDb.
 *
 * <p>Groups in NoteDb can be created by following the descriptions of {@link
 * #createForNewGroup(Project.NameKey, Repository, InternalGroupCreation)}. For reading groups from
 * NoteDb or updating them, refer to {@link #loadForGroup(Project.NameKey, Repository,
 * AccountGroup.UUID)} or {@link #loadForGroupSnapshot(Project.NameKey, Repository,
 * AccountGroup.UUID, ObjectId)}.
 *
 * <p><strong>Note:</strong> Any modification (group creation or update) only becomes permanent (and
 * hence written to NoteDb) if {@link #commit(MetaDataUpdate)} is called.
 *
 * <p><strong>Warning:</strong> This class is a low-level API for groups in NoteDb. Most code which
 * deals with internal Gerrit groups should use {@link Groups} or {@link GroupsUpdate} instead.
 *
 * <h2>Internal details</h2>
 *
 * <p>Each group is represented by a commit on a branch as defined by {@link
 * RefNames#refsGroups(AccountGroup.UUID)}. Previous versions of the group exist as older commits on
 * the same branch and can be reached by following along the parent references. New commits for
 * updates are only created if a real modification occurs.
 *
 * <p>The commit messages of all commits on that branch form the audit log for the group. The
 * messages mention any important modifications which happened for the group to avoid costly
 * computations.
 *
 * <p>Within each commit, the properties of a group are spread across three files:
 *
 * <ul>
 *   <li><em>group.config</em>, which holds all basic properties of a group (further specified by
 *       {@link GroupConfigEntry}), formatted as a JGit {@link Config} file
 *   <li><em>members</em>, which lists all members (accounts) of a group, formatted as one numeric
 *       ID per line
 *   <li><em>subgroups</em>, which lists all subgroups of a group, formatted as one UUID per line
 * </ul>
 *
 * <p>The files <em>members</em> and <em>subgroups</em> need not exist, which means that the group
 * doesn't have any members or subgroups.
 */
public class GroupConfig extends VersionedMetaData {
  @VisibleForTesting public static final String GROUP_CONFIG_FILE = "group.config";
  @VisibleForTesting static final String MEMBERS_FILE = "members";
  @VisibleForTesting static final String SUBGROUPS_FILE = "subgroups";
  private static final Pattern LINE_SEPARATOR_PATTERN = Pattern.compile("\\R");

  /**
   * Creates a {@link GroupConfig} for a new group from the {@link InternalGroupCreation} blueprint.
   * Further, optional properties can be specified by setting a {@link GroupDelta} via {@link
   * #setGroupDelta(GroupDelta, AuditLogFormatter)} on the returned {@link GroupConfig}.
   *
   * <p><strong>Note:</strong> The returned {@link GroupConfig} has to be committed via {@link
   * #commit(MetaDataUpdate)} in order to create the group for real.
   *
   * @param projectName the name of the project which holds the NoteDb commits for groups
   * @param repository the repository which holds the NoteDb commits for groups
   * @param groupCreation an {@link InternalGroupCreation} specifying all properties which are
   *     required for a new group
   * @return a {@link GroupConfig} for a group creation
   * @throws IOException if the repository can't be accessed for some reason
   * @throws ConfigInvalidException if a group with the same UUID already exists but can't be read
   *     due to an invalid format
   * @throws DuplicateKeyException if a group with the same UUID already exists
   */
  public static GroupConfig createForNewGroup(
      Project.NameKey projectName, Repository repository, InternalGroupCreation groupCreation)
      throws IOException, ConfigInvalidException, DuplicateKeyException {
    GroupConfig groupConfig = new GroupConfig(groupCreation.getGroupUUID());
    groupConfig.load(projectName, repository);
    groupConfig.setGroupCreation(groupCreation);
    return groupConfig;
  }

  /**
   * Creates a {@link GroupConfig} for an existing group.
   *
   * <p>The group is automatically loaded within this method and can be accessed via {@link
   * #getLoadedGroup()}.
   *
   * <p>It's safe to call this method for non-existing groups. In that case, {@link
   * #getLoadedGroup()} won't return any group. Thus, the existence of a group can be easily tested.
   *
   * <p>The group represented by the returned {@link GroupConfig} can be updated by setting an
   * {@link GroupDelta} via {@link #setGroupDelta(GroupDelta, AuditLogFormatter)} and committing the
   * {@link GroupConfig} via {@link #commit(MetaDataUpdate)}.
   *
   * @param projectName the name of the project which holds the NoteDb commits for groups
   * @param repository the repository which holds the NoteDb commits for groups
   * @param groupUuid the UUID of the group
   * @return a {@link GroupConfig} for the group with the specified UUID
   * @throws IOException if the repository can't be accessed for some reason
   * @throws ConfigInvalidException if the group exists but can't be read due to an invalid format
   */
  public static GroupConfig loadForGroup(
      Project.NameKey projectName, Repository repository, AccountGroup.UUID groupUuid)
      throws IOException, ConfigInvalidException {
    return loadForGroup(projectName, repository, groupUuid, null);
  }

  /**
   * Load the group for a specific revision.
   *
   * @see GroupConfig#loadForGroup(Project.NameKey, Repository, AccountGroup.UUID)
   */
  public static GroupConfig loadForGroup(
      Project.NameKey projectName,
      Repository repository,
      AccountGroup.UUID groupUuid,
      @Nullable ObjectId groupRefObjectId)
      throws IOException, ConfigInvalidException {
    GroupConfig groupConfig = new GroupConfig(groupUuid);
    if (groupRefObjectId == null) {
      groupConfig.load(projectName, repository);
    } else {
      groupConfig.load(projectName, repository, groupRefObjectId);
    }
    return groupConfig;
  }

  /**
   * Creates a {@link GroupConfig} for an existing group at a specific revision of the repository.
   *
   * <p>This method behaves nearly the same as {@link #loadForGroup(Project.NameKey, Repository,
   * AccountGroup.UUID)}. The only difference is that {@link #loadForGroup(Project.NameKey,
   * Repository, AccountGroup.UUID)} loads the group from the current state of the repository
   * whereas this method loads the group at a specific (maybe past) revision.
   *
   * @param projectName the name of the project which holds the NoteDb commits for groups
   * @param repository the repository which holds the NoteDb commits for groups
   * @param groupUuid the UUID of the group
   * @param commitId the revision of the repository at which the group should be loaded
   * @return a {@link GroupConfig} for the group with the specified UUID
   * @throws IOException if the repository can't be accessed for some reason
   * @throws ConfigInvalidException if the group exists but can't be read due to an invalid format
   */
  public static GroupConfig loadForGroupSnapshot(
      Project.NameKey projectName,
      Repository repository,
      AccountGroup.UUID groupUuid,
      ObjectId commitId)
      throws IOException, ConfigInvalidException {
    GroupConfig groupConfig = new GroupConfig(groupUuid);
    groupConfig.load(projectName, repository, commitId);
    return groupConfig;
  }

  private final AccountGroup.UUID groupUuid;
  private final String ref;

  private Optional<InternalGroup> loadedGroup = Optional.empty();
  private Optional<InternalGroupCreation> groupCreation = Optional.empty();
  private Optional<GroupDelta> groupDelta = Optional.empty();
  private AuditLogFormatter auditLogFormatter = AuditLogFormatter.createPartiallyWorkingFallBack();
  private boolean isLoaded = false;
  private boolean allowSaveEmptyName;

  private GroupConfig(AccountGroup.UUID groupUuid) {
    this.groupUuid = requireNonNull(groupUuid);
    ref = RefNames.refsGroups(groupUuid);
  }

  /**
   * Returns the group loaded from NoteDb.
   *
   * <p>If not any NoteDb commits exist for the group represented by this {@link GroupConfig}, no
   * group is returned.
   *
   * <p>After {@link #commit(MetaDataUpdate)} was called on this {@link GroupConfig}, this method
   * returns a group which is in line with the latest NoteDb commit for this group. So, after
   * creating a {@link GroupConfig} for a new group and committing it, this method can be used to
   * retrieve a representation of the created group. The same holds for the representation of an
   * updated group.
   *
   * @return the loaded group, or an empty {@link Optional} if the group doesn't exist
   */
  public Optional<InternalGroup> getLoadedGroup() {
    checkLoaded();
    return loadedGroup;
  }

  /**
   * Specifies how the current group should be updated.
   *
   * <p>If the group is newly created, the {@link GroupDelta} can be used to specify optional
   * properties.
   *
   * <p><strong>Note:</strong> This method doesn't perform the update. It only contains the
   * instructions for the update. To apply the update for real and write the result back to NoteDb,
   * call {@link #commit(MetaDataUpdate)} on this {@link GroupConfig}.
   *
   * @param groupDelta a {@link GroupDelta} with the modifications to be applied
   * @param auditLogFormatter an {@link AuditLogFormatter} for formatting the commit message in a
   *     parsable way
   */
  public void setGroupDelta(GroupDelta groupDelta, AuditLogFormatter auditLogFormatter) {
    this.groupDelta = Optional.of(groupDelta);
    this.auditLogFormatter = auditLogFormatter;
  }

  /**
   * Allows the new name of a group to be empty during creation or update.
   *
   * <p><strong>Note:</strong> This method exists only to support the migration of legacy groups
   * which don't always necessarily have a name. Nowadays, we enforce that groups always have names.
   * When we remove the migration code, we can probably remove this method as well.
   */
  public void setAllowSaveEmptyName() {
    this.allowSaveEmptyName = true;
  }

  private void setGroupCreation(InternalGroupCreation groupCreation) throws DuplicateKeyException {
    checkLoaded();
    if (loadedGroup.isPresent()) {
      throw new DuplicateKeyException(String.format("Group %s already exists", groupUuid.get()));
    }

    this.groupCreation = Optional.of(groupCreation);
  }

  @Override
  public String getRefName() {
    return ref;
  }

  @Override
  protected void onLoad() throws IOException, ConfigInvalidException {
    if (revision != null) {
      rw.reset();
      rw.markStart(revision);
      rw.sort(RevSort.REVERSE);
      RevCommit earliestCommit = rw.next();
      Instant createdOn = Instant.ofEpochSecond(earliestCommit.getCommitTime());

      Config config = readConfig(GROUP_CONFIG_FILE);
      ImmutableSet<Account.Id> members = readMembers();
      ImmutableSet<AccountGroup.UUID> subgroups = readSubgroups();
      loadedGroup =
          Optional.of(
              createFrom(groupUuid, config, members, subgroups, createdOn, revision.toObjectId()));
    }

    isLoaded = true;
  }

  @Override
  public RevCommit commit(MetaDataUpdate update) throws IOException {
    RevCommit c = super.commit(update);
    loadedGroup = Optional.of(loadedGroup.get().toBuilder().setRefState(c.toObjectId()).build());
    return c;
  }

  // TODO(issue-15517): Fix the JdkObsolete issue with Date once JGit's PersonIdent class supports
  // Instants
  @SuppressWarnings("JdkObsolete")
  @Override
  protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
    checkLoaded();
    if (!groupCreation.isPresent() && !groupDelta.isPresent()) {
      // Group was neither created nor changed. -> A new commit isn't necessary.
      return false;
    }

    if (!allowSaveEmptyName && getNewName().equals(Optional.of(""))) {
      throw new ConfigInvalidException(
          String.format("Name of the group %s must be defined", groupUuid.get()));
    }

    // Commit timestamps are internally truncated to seconds. To return the correct 'createdOn' time
    // for new groups, we explicitly need to truncate the timestamp here.
    Instant commitTimestamp =
        TimeUtil.truncateToSecond(
            groupDelta.flatMap(GroupDelta::getUpdatedOn).orElseGet(TimeUtil::now));
    commit.setAuthor(new PersonIdent(commit.getAuthor(), Date.from(commitTimestamp)));
    commit.setCommitter(new PersonIdent(commit.getCommitter(), Date.from(commitTimestamp)));

    InternalGroup updatedGroup = updateGroup(commitTimestamp);

    String commitMessage = createCommitMessage(loadedGroup, updatedGroup);
    commit.setMessage(commitMessage);

    loadedGroup = Optional.of(updatedGroup);
    groupCreation = Optional.empty();
    groupDelta = Optional.empty();

    return true;
  }

  private void checkLoaded() {
    checkState(isLoaded, "Group %s not loaded yet", groupUuid.get());
  }

  private Optional<String> getNewName() {
    if (groupDelta.isPresent()) {
      return groupDelta.get().getName().map(n -> Strings.nullToEmpty(n.get()));
    }
    if (groupCreation.isPresent()) {
      return Optional.of(Strings.nullToEmpty(groupCreation.get().getNameKey().get()));
    }
    return Optional.empty();
  }

  private InternalGroup updateGroup(Instant commitTimestamp)
      throws IOException, ConfigInvalidException {
    Config config = updateGroupProperties();

    ImmutableSet<Account.Id> originalMembers =
        loadedGroup.map(InternalGroup::getMembers).orElseGet(ImmutableSet::of);
    Optional<ImmutableSet<Account.Id>> updatedMembers = updateMembers(originalMembers);

    ImmutableSet<AccountGroup.UUID> originalSubgroups =
        loadedGroup.map(InternalGroup::getSubgroups).orElseGet(ImmutableSet::of);
    Optional<ImmutableSet<AccountGroup.UUID>> updatedSubgroups = updateSubgroups(originalSubgroups);

    Instant createdOn = loadedGroup.map(InternalGroup::getCreatedOn).orElse(commitTimestamp);

    return createFrom(
        groupUuid,
        config,
        updatedMembers.orElse(originalMembers),
        updatedSubgroups.orElse(originalSubgroups),
        createdOn,
        null);
  }

  private Config updateGroupProperties() throws IOException, ConfigInvalidException {
    Config config = readConfig(GROUP_CONFIG_FILE);
    groupCreation.ifPresent(
        internalGroupCreation ->
            Arrays.stream(GroupConfigEntry.values())
                .forEach(configEntry -> configEntry.initNewConfig(config, internalGroupCreation)));
    groupDelta.ifPresent(
        delta ->
            Arrays.stream(GroupConfigEntry.values())
                .forEach(configEntry -> configEntry.updateConfigValue(config, delta)));
    saveConfig(GROUP_CONFIG_FILE, config);
    return config;
  }

  private Optional<ImmutableSet<Account.Id>> updateMembers(ImmutableSet<Account.Id> originalMembers)
      throws IOException {
    Optional<ImmutableSet<Account.Id>> updatedMembers =
        groupDelta
            .map(GroupDelta::getMemberModification)
            .map(memberModification -> memberModification.apply(originalMembers))
            .map(ImmutableSet::copyOf)
            .filter(members -> !originalMembers.equals(members));
    if (updatedMembers.isPresent()) {
      saveMembers(updatedMembers.get());
    }
    return updatedMembers;
  }

  private Optional<ImmutableSet<AccountGroup.UUID>> updateSubgroups(
      ImmutableSet<AccountGroup.UUID> originalSubgroups) throws IOException {
    Optional<ImmutableSet<AccountGroup.UUID>> updatedSubgroups =
        groupDelta
            .map(GroupDelta::getSubgroupModification)
            .map(subgroupModification -> subgroupModification.apply(originalSubgroups))
            .map(ImmutableSet::copyOf)
            .filter(subgroups -> !originalSubgroups.equals(subgroups));
    if (updatedSubgroups.isPresent()) {
      saveSubgroups(updatedSubgroups.get());
    }
    return updatedSubgroups;
  }

  private void saveMembers(ImmutableSet<Account.Id> members) throws IOException {
    saveToFile(MEMBERS_FILE, members, member -> String.valueOf(member.get()));
  }

  private void saveSubgroups(ImmutableSet<AccountGroup.UUID> subgroups) throws IOException {
    saveToFile(SUBGROUPS_FILE, subgroups, AccountGroup.UUID::get);
  }

  private <E> void saveToFile(
      String filePath, ImmutableSet<E> elements, Function<E, String> toStringFunction)
      throws IOException {
    String fileContent = elements.stream().map(toStringFunction).collect(joining("\n"));
    saveUTF8(filePath, fileContent);
  }

  private ImmutableSet<Account.Id> readMembers() throws IOException, ConfigInvalidException {
    return readFromFile(MEMBERS_FILE, entry -> Account.id(Integer.parseInt(entry)));
  }

  private ImmutableSet<AccountGroup.UUID> readSubgroups()
      throws IOException, ConfigInvalidException {
    return readFromFile(SUBGROUPS_FILE, AccountGroup::uuid);
  }

  private <E> ImmutableSet<E> readFromFile(String filePath, Function<String, E> fromStringFunction)
      throws IOException, ConfigInvalidException {
    String fileContent = readUTF8(filePath);
    try {
      Iterable<String> lines =
          Splitter.on(LINE_SEPARATOR_PATTERN).trimResults().omitEmptyStrings().split(fileContent);
      return Streams.stream(lines).map(fromStringFunction).collect(toImmutableSet());
    } catch (NumberFormatException e) {
      throw new ConfigInvalidException(
          String.format("Invalid file %s for commit %s", filePath, revision.name()), e);
    }
  }

  private static InternalGroup createFrom(
      AccountGroup.UUID groupUuid,
      Config config,
      ImmutableSet<Account.Id> members,
      ImmutableSet<AccountGroup.UUID> subgroups,
      Instant createdOn,
      ObjectId refState)
      throws ConfigInvalidException {
    InternalGroup.Builder group = InternalGroup.builder();
    group.setGroupUUID(groupUuid);
    for (GroupConfigEntry configEntry : GroupConfigEntry.values()) {
      configEntry.readFromConfig(groupUuid, group, config);
    }
    group.setMembers(members);
    group.setSubgroups(subgroups);
    group.setCreatedOn(createdOn);
    group.setRefState(refState);
    return group.build();
  }

  private String createCommitMessage(
      Optional<InternalGroup> originalGroup, InternalGroup updatedGroup) {
    GroupConfigCommitMessage commitMessage =
        new GroupConfigCommitMessage(auditLogFormatter, updatedGroup);
    originalGroup.ifPresent(commitMessage::setOriginalGroup);
    return commitMessage.create();
  }
}
