// 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.acceptance.rest.project;

import static com.google.gerrit.acceptance.rest.project.RefAssert.assertRefNames;
import static com.google.gerrit.acceptance.rest.project.RefAssert.assertRefs;
import static org.junit.Assert.fail;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.TestProjectInput;
import com.google.gerrit.extensions.api.projects.BranchInfo;
import com.google.gerrit.extensions.api.projects.ProjectApi.ListRefsRequest;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.reviewdb.client.RefNames;
import org.junit.Test;

@NoHttpd
public class ListBranchesIT extends AbstractDaemonTest {
  @Test
  public void listBranchesOfNonExistingProject_NotFound() throws Exception {
    exception.expect(ResourceNotFoundException.class);
    gApi.projects().name("non-existing").branches().get();
  }

  @Test
  public void listBranchesOfNonVisibleProject_NotFound() throws Exception {
    blockRead("refs/*");
    setApiUser(user);
    exception.expect(ResourceNotFoundException.class);
    gApi.projects().name(project.get()).branches().get();
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void listBranchesOfEmptyProject() throws Exception {
    assertRefs(
        ImmutableList.of(branch("HEAD", null, false), branch(RefNames.REFS_CONFIG, null, false)),
        list().get());
  }

  @Test
  public void listBranches() throws Exception {
    String master = pushTo("refs/heads/master").getCommit().name();
    String dev = pushTo("refs/heads/dev").getCommit().name();
    assertRefs(
        ImmutableList.of(
            branch("HEAD", "master", false),
            branch(RefNames.REFS_CONFIG, null, false),
            branch("refs/heads/dev", dev, true),
            branch("refs/heads/master", master, false)),
        list().get());
  }

  @Test
  public void listBranchesSomeHidden() throws Exception {
    blockRead("refs/heads/dev");
    String master = pushTo("refs/heads/master").getCommit().name();
    pushTo("refs/heads/dev");
    setApiUser(user);
    // refs/meta/config is hidden since user is no project owner
    assertRefs(
        ImmutableList.of(
            branch("HEAD", "master", false), branch("refs/heads/master", master, false)),
        list().get());
  }

  @Test
  public void listBranchesHeadHidden() throws Exception {
    blockRead("refs/heads/master");
    pushTo("refs/heads/master");
    String dev = pushTo("refs/heads/dev").getCommit().name();
    setApiUser(user);
    // refs/meta/config is hidden since user is no project owner
    assertRefs(ImmutableList.of(branch("refs/heads/dev", dev, false)), list().get());
  }

  @Test
  public void listBranchesUsingPagination() throws Exception {
    pushTo("refs/heads/master");
    pushTo("refs/heads/someBranch1");
    pushTo("refs/heads/someBranch2");
    pushTo("refs/heads/someBranch3");

    // Using only limit.
    assertRefNames(
        ImmutableList.of(
            "HEAD", RefNames.REFS_CONFIG, "refs/heads/master", "refs/heads/someBranch1"),
        list().withLimit(4).get());

    // Limit higher than total number of branches.
    assertRefNames(
        ImmutableList.of(
            "HEAD",
            RefNames.REFS_CONFIG,
            "refs/heads/master",
            "refs/heads/someBranch1",
            "refs/heads/someBranch2",
            "refs/heads/someBranch3"),
        list().withLimit(25).get());

    // Using start only.
    assertRefNames(
        ImmutableList.of(
            "refs/heads/master",
            "refs/heads/someBranch1",
            "refs/heads/someBranch2",
            "refs/heads/someBranch3"),
        list().withStart(2).get());

    // Skip more branches than the number of available branches.
    assertRefNames(ImmutableList.<String>of(), list().withStart(7).get());

    // Ssing start and limit.
    assertRefNames(
        ImmutableList.of("refs/heads/master", "refs/heads/someBranch1"),
        list().withStart(2).withLimit(2).get());
  }

  @Test
  public void listBranchesUsingFilter() throws Exception {
    pushTo("refs/heads/master");
    pushTo("refs/heads/someBranch1");
    pushTo("refs/heads/someBranch2");
    pushTo("refs/heads/someBranch3");

    // Using substring.
    assertRefNames(
        ImmutableList.of(
            "refs/heads/someBranch1", "refs/heads/someBranch2", "refs/heads/someBranch3"),
        list().withSubstring("some").get());

    assertRefNames(
        ImmutableList.of(
            "refs/heads/someBranch1", "refs/heads/someBranch2", "refs/heads/someBranch3"),
        list().withSubstring("Branch").get());

    assertRefNames(
        ImmutableList.of(
            "refs/heads/someBranch1", "refs/heads/someBranch2", "refs/heads/someBranch3"),
        list().withSubstring("somebranch").get());

    // Using regex.
    assertRefNames(ImmutableList.of("refs/heads/master"), list().withRegex(".*ast.*r").get());
    assertRefNames(ImmutableList.of(), list().withRegex(".*AST.*R").get());

    // Conflicting options
    assertBadRequest(list().withSubstring("somebranch").withRegex(".*ast.*r"));
  }

  private ListRefsRequest<BranchInfo> list() throws Exception {
    return gApi.projects().name(project.get()).branches();
  }

  private static BranchInfo branch(String ref, String revision, boolean canDelete) {
    BranchInfo info = new BranchInfo();
    info.ref = ref;
    info.revision = revision;
    info.canDelete = canDelete ? true : null;
    return info;
  }

  private void assertBadRequest(ListRefsRequest<BranchInfo> req) throws Exception {
    try {
      req.get();
      fail("Expected BadRequestException");
    } catch (BadRequestException e) {
      // Expected
    }
  }
}
