// 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.googlesource.gerrit.libmodule.plugins.test;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.testing.NoteDbMode.ON;
import static com.googlesource.gerrit.modules.gitrefsfilter.ChangesTsCache.CHANGES_CACHE_TS;
import static com.googlesource.gerrit.modules.gitrefsfilter.OpenChangesCache.OPEN_CHANGES_CACHE;
import static java.util.concurrent.TimeUnit.MILLISECONDS;

import com.google.common.base.Stopwatch;
import com.google.common.cache.LoadingCache;
import com.google.gerrit.acceptance.GerritConfig;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.testing.NoteDbMode;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.name.Named;
import com.googlesource.gerrit.modules.gitrefsfilter.ChangeCacheKey;
import com.googlesource.gerrit.modules.gitrefsfilter.FilterRefsConfig;
import com.googlesource.gerrit.modules.gitrefsfilter.RefsFilterModule;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.Duration;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.util.FS;
import org.junit.Before;
import org.junit.Test;

@NoHttpd
@Sandboxed
public class GitRefsFilterTest extends AbstractGitDaemonTest {

  @Inject private PluginConfigFactory cfgFactory;

  @Inject
  private @Named(OPEN_CHANGES_CACHE) LoadingCache<ChangeCacheKey, Boolean> changeOpenCache;

  @Inject
  private @Named(CHANGES_CACHE_TS) LoadingCache<ChangeCacheKey, Long> changesTsCache;

  private static final int CLOSED_CHANGES_GRACE_TIME_SEC = 5;

  private static final Duration TEST_PATIENCE_TIME =
      Duration.ofSeconds(CLOSED_CHANGES_GRACE_TIME_SEC + 1);

  private volatile Exception getRefsException = null;

  @Override
  public Module createModule() {
    return new RefsFilterModule();
  }

  @Before
  public void setup() throws Exception {
    createFilteredRefsGroup();
    allowReadWriteToProjectConfig();
    setProjectClosedChangeGraceTime();

    // Reset client status
    GitUtil.fetch(testRepo, "refs/*:refs/*");
    testRepo.reset("refs/heads/master");
  }

  @Test
  public void testUserWithFilterOutCapabilityShouldNotSeeAbandonedChangesRefs() throws Exception {
    Timestamp changeTs = gApi.changes().id(createChangeAndAbandon()).get().updated;

    waitUntil(() -> getRefsUnchecked(user).isEmpty(), TEST_PATIENCE_TIME);
    checkGetRefsIsSuccessful();

    Timestamp filterCutoffTs =
        Timestamp.from(
            Instant.now()
                .truncatedTo(ChronoUnit.SECONDS)
                .minusSeconds(CLOSED_CHANGES_GRACE_TIME_SEC));

    assertThat(changeTs.before(filterCutoffTs)).isTrue();
  }

  @Test
  public void testUserWithFilterOutCapabilityShouldSeeJustClosedChangesRefs() throws Exception {
    createChangeAndAbandon();

    assertThat(getRefs(cloneProjectChangesRefs(user))).isNotEmpty();
  }

  @Test
  public void testUserWithFilterOutCapabilityShouldNotSeeUserEdits() throws Exception {
    createChange();
    int changeNum = changeNumOfRef(getChangesRefsAs(admin).get(0));
    gApi.changes().id(changeNum).edit().create();
    assertThat(
            fetchAllRefs(user)
                .filter((ref) -> ref.startsWith(RefNames.REFS_USERS))
                .collect(Collectors.toSet()))
        .isEmpty();
  }

  @Test
  public void testUserWithFilterOutCapabilityShouldSeeOpenChangesRefs() throws Exception {
    createChange();

    assertThat(getRefs(cloneProjectChangesRefs(user))).hasSize(1);
  }

  @Test
  public void testAdminUserShouldSeeAbandonedChangesRefsAfterGracePeriod() throws Exception {
    createChangeAndAbandon();

    waitUntil(() -> getRefsUnchecked(user).isEmpty(), TEST_PATIENCE_TIME);

    assertThat(getRefs(cloneProjectChangesRefs(admin))).isNotEmpty();
  }

  @Test
  @GerritConfig(name = "git-refs-filter.hideRefs", value = "refs/heads/sandbox/")
  public void testUserWithHideRefsShouldNotSeeSandboxBranches() throws Exception {
    String sandboxPrefix = "refs/heads/sandbox/";
    setApiUser(admin);
    createBranch(new Branch.NameKey(project, "sandbox/foo"));

    assertThat(getRefs(cloneProjectRefs(admin, "+refs/heads/*:refs/heads/*"), sandboxPrefix))
        .isNotEmpty();
    assertThat(getRefs(cloneProjectRefs(user, "+refs/heads/*:refs/heads/*"), sandboxPrefix))
        .isEmpty();
  }

  @Test
  @GerritConfig(
      name = "git-refs-filter.hideRefs",
      values = {"refs/heads/sandbox/", "!refs/heads/sandbox/mine"})
  public void testUserWithHideRefsShouldSeeItsOwnSandboxBranch() throws Exception {
    String sandboxPrefix = "refs/heads/sandbox/";
    setApiUser(admin);
    createBranch(new Branch.NameKey(project, "sandbox/mine"));

    assertThat(getRefs(cloneProjectRefs(user, "+refs/heads/*:refs/heads/*"), sandboxPrefix))
        .isNotEmpty();
  }

  @Test
  public void testShouldCacheChangeIsClosedWhenAbandoned() throws Exception {
    if (NoteDbMode.get().equals(ON)) {
      Change.Id changeId = new Change.Id(createChangeAndAbandon());
      Ref metaRef = getMetaId(changeId);

      getRefs(cloneProjectChangesRefs(user));

      assertThat(changeOpenCache.asMap().size()).isEqualTo(1);

      Map.Entry<ChangeCacheKey, Boolean> cacheEntry =
          new ArrayList<>(changeOpenCache.asMap().entrySet()).get(0);

      assertThat(cacheEntry.getKey().project()).isEqualTo(project);
      assertThat(cacheEntry.getKey().changeId()).isEqualTo(changeId);
      assertThat(cacheEntry.getKey().changeRevision()).isEqualTo(metaRef.getObjectId());
      assertThat(cacheEntry.getKey().repo()).isNotNull();
      assertThat(cacheEntry.getValue()).isFalse();
    }
  }

  @Test
  public void testShouldCacheChangeKeyContainRepoAfterDeserializing() throws Exception {
    Change.Id changeId = new Change.Id(createChangeAndAbandon());
    getRefs(cloneProjectChangesRefs(user));

    assertThat(changeOpenCache.asMap().size()).isEqualTo(1);

    Map.Entry<ChangeCacheKey, Boolean> cacheEntry =
        new ArrayList<>(changeOpenCache.asMap().entrySet()).get(0);

    assertThat(cacheEntry.getKey().repo()).isNotNull();
  }

  @Test
  public void testShouldCacheWhenChangeIsOpen() throws Exception {
    if (NoteDbMode.get().equals(ON)) {
      createChange();
      List<Ref> refs = getRefs(cloneProjectChangesRefs(user));

      assertThat(refs).isNotEmpty();

      Change.Id changeId = new Change.Id(changeNumOfRef(refs.get(0)));

      assertThat(changeOpenCache.asMap().size()).isEqualTo(1);

      Map.Entry<ChangeCacheKey, Boolean> cacheEntry =
          new ArrayList<>(changeOpenCache.asMap().entrySet()).get(0);

      assertThat(cacheEntry.getKey().project()).isEqualTo(project);
      assertThat(cacheEntry.getKey().changeId()).isEqualTo(changeId);
      assertThat(cacheEntry.getKey().changeRevision()).isEqualTo(getMetaId(changeId).getObjectId());
      assertThat(cacheEntry.getValue()).isTrue();
    }
  }

  @Test
  public void testShouldCacheChangeTsWhenAbandoned() throws Exception {
    Change.Id changeId = new Change.Id(createChangeAndAbandon());
    Ref metaRef = getMetaId(changeId);

    getRefs(cloneProjectChangesRefs(user));

    assertThat(changesTsCache.asMap().size()).isEqualTo(1);

    Map.Entry<ChangeCacheKey, Long> cacheEntry =
        new ArrayList<>(changesTsCache.asMap().entrySet()).get(0);

    assertThat(cacheEntry.getKey().project()).isEqualTo(project);
    assertThat(cacheEntry.getKey().changeId()).isEqualTo(changeId);
    assertThat(cacheEntry.getKey().changeRevision()).isEqualTo(metaRef.getObjectId());
    assertThat(cacheEntry.getValue())
        .isEqualTo(gApi.changes().id(changeId.get()).get().updated.getTime());
  }

  private List<Ref> getRefsUnchecked(TestAccount user) {
    try {
      return super.getRefs(cloneProjectChangesRefs(user));
    } catch (Exception e) {
      getRefsException = e;
      return new ArrayList<>();
    }
  }

  private void checkGetRefsIsSuccessful() throws Exception {
    if (getRefsException != null) {
      throw getRefsException;
    }
  }

  protected Stream<String> fetchAllRefs(TestAccount testAccount) throws Exception {
    DfsRepositoryDescription desc = new DfsRepositoryDescription("clone of " + project.get());

    FS fs = FS.detect();
    fs.setUserHome(null);

    InMemoryRepository dest =
        new InMemoryRepository.Builder().setRepositoryDescription(desc).setFS(fs).build();
    Config cfg = dest.getConfig();
    String uri = registerRepoConnection(project, testAccount);
    cfg.setString("remote", "origin", "url", uri);
    cfg.setString("remote", "origin", "fetch", "+refs/*:refs/remotes/origin/*");
    TestRepository<InMemoryRepository> testRepo = GitUtil.newTestRepository(dest);
    FetchResult result = testRepo.git().fetch().setRemote("origin").call();
    return result.getAdvertisedRefs().stream().map(Ref::getName);
  }

  protected List<Ref> getRefs(TestRepository<InMemoryRepository> repo, String prefix)
      throws IOException {
    return repo.getRepository().getRefDatabase().getRefsByPrefix(prefix);
  }

  private Ref getMetaId(Change.Id changeId) throws Exception {
    try (Repository r = repoManager.openRepository(project)) {
      return r.exactRef(RefNames.changeMetaRef(changeId));
    }
  }

  private void waitUntil(Supplier<Boolean> waitCondition, Duration timeout)
      throws InterruptedException {
    Stopwatch stopwatch = Stopwatch.createStarted();
    while (!waitCondition.get()) {
      if (stopwatch.elapsed().compareTo(timeout) > 0) {
        throw new InterruptedException();
      }
      MILLISECONDS.sleep(50);
    }
  }

  private void allowReadWriteToProjectConfig() throws Exception {
    try (ProjectConfigUpdate u = updateProject(project)) {
      ProjectConfig cfg = u.getConfig();
      Util.allow(cfg, Permission.READ, REGISTERED_USERS, RefNames.REFS_CONFIG);
      Util.allow(cfg, Permission.PUSH, REGISTERED_USERS, RefNames.REFS_CONFIG);
      u.save();
    }
  }

  private void setProjectClosedChangeGraceTime() throws Exception {

    String currentConfig =
        gApi.projects()
            .name(project.get())
            .branch(RefNames.REFS_CONFIG)
            .file(ProjectConfig.PROJECT_CONFIG)
            .asString();

    Config cfg = new Config();
    cfg.fromText(currentConfig);
    cfg.setLong(
        "plugin",
        "gerrit",
        FilterRefsConfig.PROJECT_CONFIG_CLOSED_CHANGES_GRACE_TIME_SEC,
        CLOSED_CHANGES_GRACE_TIME_SEC);
    String newConfig = cfg.toText();

    // Fetch permission ref
    GitUtil.fetch(testRepo, "refs/meta/config:cfg");
    testRepo.reset("cfg");

    PushOneCommit push =
        pushFactory.create(
            db, admin.getIdent(), testRepo, "Subject", ProjectConfig.PROJECT_CONFIG, newConfig);
    PushOneCommit.Result result = push.to(RefNames.REFS_CONFIG);
    result.assertOkStatus();
    projectCache.evict(project);
  }
}
