// Copyright (C) 2018 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 com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.gerrit.entities.InternalGroup;
import java.util.Optional;
import java.util.Set;
import java.util.StringJoiner;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Stream;
import org.eclipse.jgit.revwalk.FooterKey;

/**
 * A parsable commit message for a NoteDb commit of a group.
 *
 * <p>For group creations, it's sufficient to simply call the constructor of this class. For
 * updates, {@link #setOriginalGroup(InternalGroup)} has to be called as well.
 */
class GroupConfigCommitMessage {
  static final FooterKey FOOTER_ADD_MEMBER = new FooterKey("Add");
  static final FooterKey FOOTER_REMOVE_MEMBER = new FooterKey("Remove");
  static final FooterKey FOOTER_ADD_GROUP = new FooterKey("Add-group");
  static final FooterKey FOOTER_REMOVE_GROUP = new FooterKey("Remove-group");

  private final AuditLogFormatter auditLogFormatter;
  private final InternalGroup updatedGroup;
  private Optional<InternalGroup> originalGroup = Optional.empty();

  GroupConfigCommitMessage(AuditLogFormatter auditLogFormatter, InternalGroup updatedGroup) {
    this.auditLogFormatter = auditLogFormatter;
    this.updatedGroup = updatedGroup;
  }

  public void setOriginalGroup(InternalGroup originalGroup) {
    this.originalGroup = Optional.of(originalGroup);
  }

  public String create() {
    String summaryLine = originalGroup.isPresent() ? "Update group" : "Create group";

    StringJoiner footerJoiner = new StringJoiner("\n", "\n\n", "");
    footerJoiner.setEmptyValue("");
    Streams.concat(
            getFooterForRename().stream(),
            getFootersForMemberModifications(),
            getFootersForSubgroupModifications())
        .sorted()
        .forEach(footerJoiner::add);
    String footer = footerJoiner.toString();

    return summaryLine + footer;
  }

  private Optional<String> getFooterForRename() {
    if (!originalGroup.isPresent()) {
      return Optional.empty();
    }

    String originalName = originalGroup.get().getName();
    String newName = updatedGroup.getName();
    if (originalName.equals(newName)) {
      return Optional.empty();
    }
    return Optional.of("Rename from " + originalName + " to " + newName);
  }

  private Stream<String> getFootersForMemberModifications() {
    return getFooters(
        InternalGroup::getMembers,
        AuditLogFormatter::getParsableAccount,
        FOOTER_ADD_MEMBER,
        FOOTER_REMOVE_MEMBER);
  }

  private Stream<String> getFootersForSubgroupModifications() {
    return getFooters(
        InternalGroup::getSubgroups,
        AuditLogFormatter::getParsableGroup,
        FOOTER_ADD_GROUP,
        FOOTER_REMOVE_GROUP);
  }

  private <T> Stream<String> getFooters(
      Function<InternalGroup, Set<T>> getElements,
      BiFunction<AuditLogFormatter, T, String> toParsableString,
      FooterKey additionFooterKey,
      FooterKey removalFooterKey) {
    Set<T> oldElements = originalGroup.map(getElements).orElseGet(ImmutableSet::of);
    Set<T> newElements = getElements.apply(updatedGroup);

    Function<T, String> toString = element -> toParsableString.apply(auditLogFormatter, element);

    Stream<String> removedElements =
        Sets.difference(oldElements, newElements).stream()
            .map(toString)
            .map((removalFooterKey.getName() + ": ")::concat);
    Stream<String> addedElements =
        Sets.difference(newElements, oldElements).stream()
            .map(toString)
            .map((additionFooterKey.getName() + ": ")::concat);
    return Stream.concat(removedElements, addedElements);
  }
}
