// 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.git.meta;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Project;
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.meta.VersionedMetaData.BatchMetaDataUpdate;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.TestTimeUtil;
import java.io.IOException;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.dfs.DfsRepositoryDescription;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class VersionedMetaDataTest {
  // If you're considering fleshing out this test and making it more comprehensive, please consider
  // instead coming up with a replacement interface for
  // VersionedMetaData/BatchMetaDataUpdate/MetaDataUpdate that is easier to use correctly.

  private static final ZoneId ZONE_ID = ZoneId.of("America/Los_Angeles");
  private static final String DEFAULT_REF = "refs/meta/config";

  private Project.NameKey project;
  private Repository repo;

  @Before
  public void setUp() {
    TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
    project = Project.nameKey("repo");
    repo = new InMemoryRepository(new DfsRepositoryDescription(project.get()));
  }

  @After
  public void tearDown() {
    TestTimeUtil.useSystemTime();
  }

  @Test
  public void singleUpdate() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(3);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(3, "Increment conf.value by 3");
  }

  @Test
  public void noOpNoSetter() throws Exception {
    MyMetaData d = load(0);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(0);
  }

  @Test
  public void noOpWithSetter() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(0);
    d.commit(newMetaDataUpdate());
    // First commit is actually not a no-op because it creates an empty config file.
    assertMyMetaData(0, "Increment conf.value by 0");

    d = load(0);
    d.setIncrement(0);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(0, "Increment conf.value by 0");
  }

  @Test
  public void multipleSeparateUpdatesWithSameObject() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(1);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(1, "Increment conf.value by 1");
    d.setIncrement(2);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(3, "Increment conf.value by 1", "Increment conf.value by 2");
  }

  @Test
  public void multipleSeparateUpdatesWithDifferentObject() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(1);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(1, "Increment conf.value by 1");

    d = load(1);
    d.setIncrement(2);
    d.commit(newMetaDataUpdate());
    assertMyMetaData(3, "Increment conf.value by 1", "Increment conf.value by 2");
  }

  @Test
  public void multipleUpdatesInBatchWithSameObject() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(1);
    try (BatchMetaDataUpdate batch = d.openUpdate(newMetaDataUpdate())) {
      batch.write(d, newCommitBuilder());
      assertMyMetaData(0); // Batch not yet committed.

      d.setIncrement(2);
      batch.write(d, newCommitBuilder());
      batch.commit();
    }

    assertMyMetaData(3, "Increment conf.value by 1", "Increment conf.value by 2");
  }

  @Test
  public void multipleUpdatesSomeNoOps() throws Exception {
    MyMetaData d = load(0);
    d.setIncrement(1);
    try (BatchMetaDataUpdate batch = d.openUpdate(newMetaDataUpdate())) {
      batch.write(d, newCommitBuilder());
      assertMyMetaData(0); // Batch not yet committed.

      d.setIncrement(0);
      batch.write(d, newCommitBuilder());
      assertMyMetaData(0); // Batch not yet committed.

      d.setIncrement(3);
      batch.write(d, newCommitBuilder());
      batch.commit();
    }

    assertMyMetaData(4, "Increment conf.value by 1", "Increment conf.value by 3");
  }

  @Test
  public void sharedBatchRefUpdate() throws Exception {
    MyMetaData d1 = load("refs/meta/1", 0);
    MyMetaData d2 = load("refs/meta/2", 0);

    BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
    try (BatchMetaDataUpdate batch1 = d1.openUpdate(newMetaDataUpdate(bru));
        BatchMetaDataUpdate batch2 = d2.openUpdate(newMetaDataUpdate(bru))) {
      d1.setIncrement(1);
      batch1.write(d1, newCommitBuilder());

      d2.setIncrement(2000);
      batch2.write(d2, newCommitBuilder());

      d1.setIncrement(3);
      batch1.write(d1, newCommitBuilder());

      d2.setIncrement(4000);
      batch2.write(d2, newCommitBuilder());

      batch1.commit();
      batch2.commit();
    }

    assertMyMetaData(d1.getRefName(), 0);
    assertMyMetaData(d2.getRefName(), 0);
    assertThat(bru.getCommands().stream().map(ReceiveCommand::getRefName))
        .containsExactly("refs/meta/1", "refs/meta/2");
    RefUpdateUtil.executeChecked(bru, repo);

    assertMyMetaData(d1.getRefName(), 4, "Increment conf.value by 1", "Increment conf.value by 3");
    assertMyMetaData(
        d2.getRefName(), 6000, "Increment conf.value by 2000", "Increment conf.value by 4000");
  }

  private MyMetaData load(int expectedValue) throws Exception {
    return load(DEFAULT_REF, expectedValue);
  }

  private MyMetaData load(String ref, int expectedValue) throws Exception {
    MyMetaData d = new MyMetaData(ref);
    d.load(project, repo);
    assertThat(d.getValue()).isEqualTo(expectedValue);
    return d;
  }

  private MetaDataUpdate newMetaDataUpdate() {
    return newMetaDataUpdate(null);
  }

  private MetaDataUpdate newMetaDataUpdate(@Nullable BatchRefUpdate bru) {
    MetaDataUpdate u = new MetaDataUpdate(GitReferenceUpdated.DISABLED, project, repo, bru);
    CommitBuilder cb = newCommitBuilder();
    u.getCommitBuilder().setAuthor(cb.getAuthor());
    u.getCommitBuilder().setCommitter(cb.getCommitter());
    return u;
  }

  private CommitBuilder newCommitBuilder() {
    CommitBuilder cb = new CommitBuilder();
    PersonIdent author =
        new PersonIdent("J. Author", "author@example.com", TimeUtil.now(), ZONE_ID);
    cb.setAuthor(author);
    cb.setCommitter(
        new PersonIdent(
            "M. Committer", "committer@example.com", author.getWhen(), author.getTimeZone()));
    return cb;
  }

  private void assertMyMetaData(String ref, int expectedValue, String... expectedLog)
      throws Exception {
    MyMetaData d = load(ref, expectedValue);
    assertThat(log(d)).containsExactlyElementsIn(Arrays.asList(expectedLog)).inOrder();
  }

  private void assertMyMetaData(int expectedValue, String... expectedLog) throws Exception {
    assertMyMetaData(DEFAULT_REF, expectedValue, expectedLog);
  }

  private ImmutableList<String> log(MyMetaData d) throws Exception {
    try (RevWalk rw = new RevWalk(repo)) {
      Ref ref = repo.exactRef(d.getRefName());
      if (ref == null) {
        return ImmutableList.of();
      }
      rw.sort(RevSort.REVERSE);
      rw.setRetainBody(true);
      rw.markStart(rw.parseCommit(ref.getObjectId()));
      return Streams.stream(rw).map(RevCommit::getFullMessage).collect(toImmutableList());
    }
  }

  private static class MyMetaData extends VersionedMetaData {
    private static final String CONFIG_FILE = "my.config";
    private static final String SECTION = "conf";
    private static final String NAME = "value";

    private final String ref;

    MyMetaData(String ref) {
      this.ref = ref;
    }

    @Override
    protected String getRefName() {
      return ref;
    }

    private int curr;
    private Optional<Integer> increment = Optional.empty();

    @Override
    protected void onLoad() throws IOException, ConfigInvalidException {
      Config cfg = readConfig(CONFIG_FILE);
      curr = cfg.getInt(SECTION, null, NAME, 0);
    }

    int getValue() {
      return curr;
    }

    void setIncrement(int increment) {
      checkArgument(increment >= 0, "increment must be positive: %s", increment);
      this.increment = Optional.of(increment);
    }

    @Override
    protected boolean onSave(CommitBuilder cb) throws IOException, ConfigInvalidException {
      // Two ways to produce a no-op: don't call setIncrement, and call setIncrement(0);
      if (!increment.isPresent()) {
        return false;
      }
      Config cfg = readConfig(CONFIG_FILE);
      cfg.setInt(SECTION, null, NAME, cfg.getInt(SECTION, null, NAME, 0) + increment.get());
      cb.setMessage(String.format("Increment %s.%s by %d", SECTION, NAME, increment.get()));
      saveConfig(CONFIG_FILE, cfg);
      increment = Optional.empty();
      return true;
    }
  }
}
