// Copyright (C) 2013 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.change;

import com.google.gerrit.common.data.IncludedInDetail;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
import org.eclipse.jgit.junit.RepositoryTestCase;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class IncludedInResolverTest extends RepositoryTestCase {

  // Branch names
  private static final String BRANCH_MASTER = "master";
  private static final String BRANCH_1_0 = "rel-1.0";
  private static final String BRANCH_1_3 = "rel-1.3";
  private static final String BRANCH_2_0 = "rel-2.0";
  private static final String BRANCH_2_5 = "rel-2.5";

  // Tag names
  private static final String TAG_1_0 = "1.0";
  private static final String TAG_1_0_1 = "1.0.1";
  private static final String TAG_1_3 = "1.3";
  private static final String TAG_2_0_1 = "2.0.1";
  private static final String TAG_2_0 = "2.0";
  private static final String TAG_2_5 = "2.5";
  private static final String TAG_2_5_ANNOTATED = "2.5-annotated";
  private static final String TAG_2_5_ANNOTATED_TWICE = "2.5-annotated_twice";

  // Commits
  private RevCommit commit_initial;
  private RevCommit commit_v1_3;
  private RevCommit commit_v2_5;

  private List<String> expTags = new ArrayList<>();
  private List<String> expBranches = new ArrayList<>();

  private RevWalk revWalk;

  @Before
  public void setUp() throws Exception {
    super.setUp();

    /*- The following graph will be created.

      o   tag 2.5, 2.5_annotated, 2.5_annotated_twice
      |\
      | o tag 2.0.1
      | o tag 2.0
      o | tag 1.3
      |/
      o   c3

      | o tag 1.0.1
      |/
      o   tag 1.0
      o   c2
      o   c1

     */

    Git git = new Git(db);
    revWalk = new RevWalk(db);
    // Version 1.0
    commit_initial = git.commit().setMessage("c1").call();
    git.commit().setMessage("c2").call();
    RevCommit commit_v1_0 = git.commit().setMessage("version 1.0").call();
    git.tag().setName(TAG_1_0).setObjectId(commit_v1_0).call();
    RevCommit c3 = git.commit().setMessage("c3").call();
    // Version 1.01
    createAndCheckoutBranch(commit_v1_0, BRANCH_1_0);
    RevCommit commit_v1_0_1 =
        git.commit().setMessage("verREFS_HEADS_RELsion 1.0.1").call();
    git.tag().setName(TAG_1_0_1).setObjectId(commit_v1_0_1).call();
    // Version 1.3
    createAndCheckoutBranch(c3, BRANCH_1_3);
    commit_v1_3 = git.commit().setMessage("version 1.3").call();
    git.tag().setName(TAG_1_3).setObjectId(commit_v1_3).call();
    // Version 2.0
    createAndCheckoutBranch(c3, BRANCH_2_0);
    RevCommit commit_v2_0 = git.commit().setMessage("version 2.0").call();
    git.tag().setName(TAG_2_0).setObjectId(commit_v2_0).call();
    RevCommit commit_v2_0_1 = git.commit().setMessage("version 2.0.1").call();
    git.tag().setName(TAG_2_0_1).setObjectId(commit_v2_0_1).call();

    // Version 2.5
    createAndCheckoutBranch(commit_v1_3, BRANCH_2_5);
    git.merge().include(commit_v2_0_1).setCommit(false)
        .setFastForward(FastForwardMode.NO_FF).call();
    commit_v2_5 = git.commit().setMessage("version 2.5").call();
    git.tag().setName(TAG_2_5).setObjectId(commit_v2_5).setAnnotated(false)
        .call();
    Ref ref_tag_2_5_annotated =
        git.tag().setName(TAG_2_5_ANNOTATED).setObjectId(commit_v2_5)
            .setAnnotated(true).call();
    RevTag tag_2_5_annotated =
        revWalk.parseTag(ref_tag_2_5_annotated.getObjectId());
    git.tag().setName(TAG_2_5_ANNOTATED_TWICE).setObjectId(tag_2_5_annotated)
        .setAnnotated(true).call();
  }

  @After
  public void tearDown() throws Exception {
    revWalk.close();
    super.tearDown();
  }

  @Test
  public void resolveLatestCommit() throws Exception {
    // Check tip commit
    IncludedInDetail detail = resolve(commit_v2_5);

    // Check that only tags and branches which refer the tip are returned
    expTags.add(TAG_2_5);
    expTags.add(TAG_2_5_ANNOTATED);
    expTags.add(TAG_2_5_ANNOTATED_TWICE);
    assertEquals(expTags, detail.getTags());
    expBranches.add(BRANCH_2_5);
    assertEquals(expBranches, detail.getBranches());
  }

  @Test
  public void resolveFirstCommit() throws Exception {
    // Check first commit
    IncludedInDetail detail = resolve(commit_initial);

    // Check whether all tags and branches are returned
    expTags.add(TAG_1_0);
    expTags.add(TAG_1_0_1);
    expTags.add(TAG_1_3);
    expTags.add(TAG_2_0);
    expTags.add(TAG_2_0_1);
    expTags.add(TAG_2_5);
    expTags.add(TAG_2_5_ANNOTATED);
    expTags.add(TAG_2_5_ANNOTATED_TWICE);
    assertEquals(expTags, detail.getTags());

    expBranches.add(BRANCH_MASTER);
    expBranches.add(BRANCH_1_0);
    expBranches.add(BRANCH_1_3);
    expBranches.add(BRANCH_2_0);
    expBranches.add(BRANCH_2_5);
    assertEquals(expBranches, detail.getBranches());
  }

  @Test
  public void resolveBetwixtCommit() throws Exception {
    // Check a commit somewhere in the middle
    IncludedInDetail detail = resolve(commit_v1_3);

    // Check whether all succeeding tags and branches are returned
    expTags.add(TAG_1_3);
    expTags.add(TAG_2_5);
    expTags.add(TAG_2_5_ANNOTATED);
    expTags.add(TAG_2_5_ANNOTATED_TWICE);
    assertEquals(expTags, detail.getTags());

    expBranches.add(BRANCH_1_3);
    expBranches.add(BRANCH_2_5);
    assertEquals(expBranches, detail.getBranches());
  }

  private IncludedInDetail resolve(RevCommit commit) throws Exception {
    return IncludedInResolver.resolve(db, revWalk, commit);
  }

  private void assertEquals(List<String> list1, List<String> list2) {
    Collections.sort(list1);
    Collections.sort(list2);
    Assert.assertEquals(list1, list2);
  }

  private void createAndCheckoutBranch(ObjectId objectId, String branchName)
      throws IOException {
    String fullBranchName = "refs/heads/" + branchName;
    super.createBranch(objectId, fullBranchName);
    super.checkoutBranch(fullBranchName);
  }
}
