// 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(
            Streams.stream(getFooterForRename()),
            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);
  }
}
