// 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;

import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toList;

import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.extensions.events.ChangeMergedListener;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jgit.errors.ConfigInvalidException;

/**
 * With groups in NoteDb, the capability of creating a group is expressed as a {@code CREATE}
 * permission on {@code refs/groups/*} rather than a global capability in {@code All-Projects}.
 *
 * <p>During the transition phase, we have to keep these permissions in sync with the global
 * capabilities that serve as the source of truth.
 *
 * <p>This class implements a one-way synchronization from the global {@code CREATE_GROUP}
 * capability in {@code All-Projects} to a {@code CREATE} permission on {@code refs/groups/*} in
 * {@code All-Users}.
 */
@Singleton
public class CreateGroupPermissionSyncer implements ChangeMergedListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private final AllProjectsName allProjects;
  private final AllUsersName allUsers;
  private final ProjectCache projectCache;
  private final Provider<MetaDataUpdate.Server> metaDataUpdateFactory;
  private final ProjectConfig.Factory projectConfigFactory;

  @Inject
  CreateGroupPermissionSyncer(
      AllProjectsName allProjects,
      AllUsersName allUsers,
      ProjectCache projectCache,
      Provider<MetaDataUpdate.Server> metaDataUpdateFactory,
      ProjectConfig.Factory projectConfigFactory) {
    this.allProjects = allProjects;
    this.allUsers = allUsers;
    this.projectCache = projectCache;
    this.metaDataUpdateFactory = metaDataUpdateFactory;
    this.projectConfigFactory = projectConfigFactory;
  }

  /**
   * Checks if {@code GlobalCapability.CREATE_GROUP} and {@code CREATE} permission on {@code
   * refs/groups/*} have diverged and syncs them by applying the {@code CREATE} permission to {@code
   * refs/groups/*}.
   */
  public void syncIfNeeded() throws IOException, ConfigInvalidException {
    ProjectState allProjectsState = projectCache.checkedGet(allProjects);
    requireNonNull(
        allProjectsState, () -> String.format("Can't obtain project state for %s", allProjects));
    ProjectState allUsersState = projectCache.checkedGet(allUsers);
    requireNonNull(
        allUsersState, () -> String.format("Can't obtain project state for %s", allUsers));

    Set<PermissionRule> createGroupsGlobal =
        new HashSet<>(allProjectsState.getCapabilityCollection().createGroup);
    Set<PermissionRule> createGroupsRef = new HashSet<>();

    AccessSection allUsersCreateGroupAccessSection =
        allUsersState.getConfig().getAccessSection(RefNames.REFS_GROUPS + "*");
    if (allUsersCreateGroupAccessSection != null) {
      Permission create = allUsersCreateGroupAccessSection.getPermission(Permission.CREATE);
      if (create != null && create.getRules() != null) {
        createGroupsRef.addAll(create.getRules());
      }
    }

    if (Sets.symmetricDifference(createGroupsGlobal, createGroupsRef).isEmpty()) {
      // Nothing to sync
      return;
    }

    try (MetaDataUpdate md = metaDataUpdateFactory.get().create(allUsers)) {
      ProjectConfig config = projectConfigFactory.read(md);
      AccessSection createGroupAccessSection =
          config.getAccessSection(RefNames.REFS_GROUPS + "*", true);
      if (createGroupsGlobal.isEmpty()) {
        createGroupAccessSection.setPermissions(
            createGroupAccessSection.getPermissions().stream()
                .filter(p -> !Permission.CREATE.equals(p.getName()))
                .collect(toList()));
        config.replace(createGroupAccessSection);
      } else {
        Permission createGroupPermission = new Permission(Permission.CREATE);
        createGroupAccessSection.addPermission(createGroupPermission);
        createGroupsGlobal.forEach(createGroupPermission::add);
        // The create permission is managed by Gerrit at this point only so there is no concern of
        // overwriting user-defined permissions here.
        config.replace(createGroupAccessSection);
      }

      config.commit(md);
      projectCache.evict(config.getProject());
    }
  }

  @Override
  public void onChangeMerged(Event event) {
    if (!allProjects.get().equals(event.getChange().project)
        || !RefNames.REFS_CONFIG.equals(event.getChange().branch)) {
      return;
    }
    try {
      syncIfNeeded();
    } catch (IOException | ConfigInvalidException e) {
      logger.atSevere().withCause(e).log("Can't sync create group permissions");
    }
  }
}
