// Copyright (C) 2020 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.submit;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.Truth8.assertThat;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmoduleSubscription;
import com.google.gerrit.server.git.CodeReviewCommit;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;

public class SubmoduleCommitsTest {

  private static final String MASTER = "refs/heads/master";
  private static final Project.NameKey superProject = Project.nameKey("superproject");
  private static final Project.NameKey subProject = Project.nameKey("subproject");

  private static final PersonIdent ident = new PersonIdent("submodule-test", "a@b.com");

  private InMemoryRepositoryManager repoManager = new InMemoryRepositoryManager();
  private MergeOpRepoManager mergeOpRepoManager;

  @Rule public final MockitoRule mockito = MockitoJUnit.rule();
  @Mock private ProjectCache mockProjectCache;
  @Mock private ProjectState mockProjectState;

  @Test
  public void createGitlinksCommit_subprojectMoved() throws Exception {
    createRepo(subProject, MASTER);
    createRepo(superProject, MASTER);

    when(mockProjectCache.get(any())).thenReturn(Optional.of(mockProjectState));
    mergeOpRepoManager = new MergeOpRepoManager(repoManager, mockProjectCache, null, null);

    ObjectId subprojectCommit = getTip(subProject, MASTER);
    RevCommit superprojectTip =
        directUpdateSubmodule(superProject, MASTER, Project.nameKey("dir-x"), subprojectCommit);
    assertThat(readGitLink(superProject, superprojectTip, "dir-x")).isEqualTo(subprojectCommit);

    RevCommit newSubprojectCommit = addCommit(subProject, MASTER);

    BranchNameKey superBranch = BranchNameKey.create(superProject, MASTER);
    BranchNameKey subBranch = BranchNameKey.create(subProject, MASTER);
    SubmoduleSubscription ss = new SubmoduleSubscription(superBranch, subBranch, "dir-x");
    SubmoduleCommits helper = new SubmoduleCommits(mergeOpRepoManager, ident, new Config());
    Optional<CodeReviewCommit> newGitLinksCommit =
        helper.composeGitlinksCommit(
            BranchNameKey.create(superProject, MASTER), ImmutableList.of(ss));

    assertThat(newGitLinksCommit).isPresent();
    assertThat(newGitLinksCommit.get().getParent(0)).isEqualTo(superprojectTip);
    assertThat(readGitLink(superProject, newGitLinksCommit.get(), "dir-x"))
        .isEqualTo(newSubprojectCommit);
  }

  @Test
  public void amendGitlinksCommit_subprojectMoved() throws Exception {
    createRepo(subProject, MASTER);
    createRepo(superProject, MASTER);

    when(mockProjectCache.get(any())).thenReturn(Optional.of(mockProjectState));
    mergeOpRepoManager = new MergeOpRepoManager(repoManager, mockProjectCache, null, null);

    ObjectId subprojectCommit = getTip(subProject, MASTER);
    CodeReviewCommit superprojectTip =
        directUpdateSubmodule(superProject, MASTER, Project.nameKey("dir-x"), subprojectCommit);
    assertThat(readGitLink(superProject, superprojectTip, "dir-x")).isEqualTo(subprojectCommit);

    RevCommit newSubprojectCommit = addCommit(subProject, MASTER);

    BranchNameKey superBranch = BranchNameKey.create(superProject, MASTER);
    BranchNameKey subBranch = BranchNameKey.create(subProject, MASTER);
    SubmoduleSubscription ss = new SubmoduleSubscription(superBranch, subBranch, "dir-x");
    SubmoduleCommits helper = new SubmoduleCommits(mergeOpRepoManager, ident, new Config());
    CodeReviewCommit amendedCommit =
        helper.amendGitlinksCommit(
            BranchNameKey.create(superProject, MASTER), superprojectTip, ImmutableList.of(ss));

    assertThat(amendedCommit.getParent(0)).isEqualTo(superprojectTip.getParent(0));
    assertThat(readGitLink(superProject, amendedCommit, "dir-x")).isEqualTo(newSubprojectCommit);
  }

  /** Create repo with a commit on refName */
  private void createRepo(Project.NameKey projectKey, String refName) throws Exception {
    Repository repo = repoManager.createRepository(projectKey);
    try (TestRepository<Repository> git = new TestRepository<>(repo)) {
      RevCommit newCommit = git.commit().message("Initial commit for " + projectKey).create();
      git.update(refName, newCommit);
    }
  }

  private ObjectId getTip(Project.NameKey projectKey, String refName)
      throws RepositoryNotFoundException, IOException {
    return repoManager.openRepository(projectKey).exactRef(refName).getObjectId();
  }

  private RevCommit addCommit(Project.NameKey projectKey, String refName) throws Exception {
    try (Repository serverRepo = repoManager.openRepository(projectKey);
        RevWalk rw = new RevWalk(serverRepo);
        TestRepository<Repository> git = new TestRepository<>(serverRepo, rw)) {
      Ref ref = serverRepo.exactRef(refName);
      assertWithMessage(refName).that(ref).isNotNull();

      RevCommit originalTip = rw.parseCommit(ref.getObjectId());
      RevCommit newTip =
          git.commit().parent(originalTip).message("Added commit to " + projectKey).create();
      git.update(refName, newTip);
      return newTip;
    }
  }

  private CodeReviewCommit directUpdateSubmodule(
      Project.NameKey project, String refName, Project.NameKey path, AnyObjectId id)
      throws Exception {
    OpenRepo or = mergeOpRepoManager.getRepo(project);
    Repository serverRepo = or.repo;
    ObjectInserter ins = or.ins;
    CodeReviewRevWalk rw = or.rw;
    Ref ref = serverRepo.exactRef(refName);
    assertWithMessage(refName).that(ref).isNotNull();
    ObjectId oldCommitId = ref.getObjectId();

    DirCache dc = DirCache.newInCore();
    DirCacheBuilder b = dc.builder();
    b.addTree(new byte[0], DirCacheEntry.STAGE_0, rw.getObjectReader(), rw.parseTree(oldCommitId));
    b.finish();
    DirCacheEditor e = dc.editor();
    e.add(
        new PathEdit(path.get()) {
          @Override
          public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.GITLINK);
            ent.setObjectId(id);
          }
        });
    e.finish();

    CommitBuilder cb = new CommitBuilder();
    cb.addParentId(oldCommitId);
    cb.setTreeId(dc.writeTree(ins));

    cb.setAuthor(ident);
    cb.setCommitter(ident);
    cb.setMessage("Direct update submodule " + path);
    ObjectId newCommitId = ins.insert(cb);
    ins.flush();

    RefUpdate ru = serverRepo.updateRef(refName);
    ru.setExpectedOldObjectId(oldCommitId);
    ru.setNewObjectId(newCommitId);
    testRefAction(() -> assertThat(ru.update()).isEqualTo(RefUpdate.Result.FAST_FORWARD));
    return rw.parseCommit(newCommitId);
  }

  private ObjectId readGitLink(Project.NameKey projectKey, RevCommit commit, String path)
      throws IOException, NoSuchProjectException {
    // SubmoduleCommitHelper used mergeOpRepoManager to create the commit
    // Read the repo from mergeOpRepoManager to get also the RevWalk that created the commit
    return readGitLinkInCommit(mergeOpRepoManager.getRepo(projectKey).rw, commit, path);
  }

  private ObjectId readGitLinkInCommit(RevWalk rw, RevCommit commit, String path)
      throws IOException {
    DirCache dc = DirCache.newInCore();
    DirCacheBuilder b = dc.builder();
    b.addTree(
        new byte[0], // no prefix path
        DirCacheEntry.STAGE_0, // standard stage
        rw.getObjectReader(),
        commit.getTree());
    b.finish();
    DirCacheEntry entry = dc.getEntry(path);
    assertThat(entry.getFileMode()).isEqualTo(FileMode.GITLINK);
    return entry.getObjectId();
  }
}
