// Copyright (C) 2022 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.permissions;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.git.ChangesByProjectCache;
import com.google.gerrit.server.query.change.ChangeData;
import java.io.IOException;
import java.util.HashMap;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.Repository;

/**
 * This class can tell efficiently if changes are visible to a user. It is intended to be used when
 * serving Git traffic on the Git wire protocol and in similar use cases when we need to know
 * efficiently if a (potentially large number) of changes are visible to a user.
 *
 * <p>The efficiency of this class comes from heuristic optimization:
 *
 * <ul>
 *   <li>For a low number of expected checks, we check visibility one-by-one.
 *   <li>For a high number of expected checks we use the ChangesByProjectCache.
 * </ul>
 *
 * <p>Changes that fail to load are pretended to be invisible. This is important on the Git paths as
 * we don't want to advertise change refs where we were unable to check the visibility (e.g. due to
 * data corruption on that change). At the same time, the overall operation should succeed as
 * otherwise a single broken change would break Git operations for an entire repo.
 */
public class GitVisibleChangeFilter {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  private static final int CHANGE_LIMIT_FOR_DIRECT_FILTERING = 5;

  private GitVisibleChangeFilter() {}

  /** Returns a map of all visible changes. Might pretend old changes are invisible. */
  static ImmutableMap<Change.Id, ChangeData> getVisibleChanges(
      ChangesByProjectCache changesByProjectCache,
      ChangeData.Factory changeDataFactory,
      Project.NameKey projectName,
      PermissionBackend.ForProject forProject,
      Repository repository,
      ImmutableSet<Change.Id> changes) {
    Stream<ChangeData> changeDatas = Stream.empty();
    if (changes.size() < CHANGE_LIMIT_FOR_DIRECT_FILTERING) {
      logger.atFine().log("Loading changes one by one for project %s", projectName);
      changeDatas = loadChangeDatasOneByOne(changes, changeDataFactory, projectName);
    } else {
      logger.atFine().log("Loading changes from ChangesByProjectCache for project %s", projectName);
      try {
        changeDatas = changesByProjectCache.streamChangeDatas(projectName, repository);
      } catch (IOException e) {
        logger.atWarning().withCause(e).log("Unable to streamChangeDatas for %s", projectName);
      }
    }
    HashMap<Change.Id, ChangeData> result = new HashMap<>();
    changeDatas
        .filter(cd -> changes.contains(cd.getId()))
        .filter(
            cd -> {
              try {
                return forProject.change(cd).test(ChangePermission.READ);
              } catch (PermissionBackendException e) {
                // This is almost the same as the message .testOrFalse() would log, but with the
                // added context of the change and coming from this class
                logger.atWarning().withCause(e).log(
                    "Cannot test read permission for %s; assuming not visible", cd);
                return false;
              }
            })
        .forEach(
            cd -> {
              if (result.containsKey(cd.getId())) {
                logger.atWarning().log(
                    "Duplicate change datas for the repo %s: [%s, %s]",
                    projectName, cd, result.get(cd.getId()));
              }
              result.put(cd.getId(), cd);
            });
    return ImmutableMap.copyOf(result);
  }

  /** Get a stream of changes by loading them individually. */
  private static Stream<ChangeData> loadChangeDatasOneByOne(
      Set<Change.Id> ids, ChangeData.Factory changeDataFactory, Project.NameKey projectName) {
    return ids.stream()
        .map(
            id -> {
              try {
                ChangeData cd = changeDataFactory.create(projectName, id);
                cd.notes(); // Make sure notes are available. This will trigger loading notes and
                // throw an exception in case the change is corrupt and can't be loaded. It will
                // then be omitted from the result.
                return cd;
              } catch (Exception e) {
                // We drop changes that we can't load. The repositories contain 'dead' change refs
                // and we want to overall operation to continue.
                logger.atFinest().withCause(e).log("Can't load Change notes for %s", id);
                return null;
              }
            })
        .filter(Objects::nonNull);
  }
}
