// 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.BranchAssert.assertBranches;
import static com.google.gerrit.acceptance.rest.project.BranchAssert.assertRefNames;

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.ResourceNotFoundException;

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(project, "refs/*");
    setApiUser(user);
    exception.expect(ResourceNotFoundException.class);
    gApi.projects().name(project.get()).branches().get();
  }

  @Test
  @TestProjectInput(createEmptyCommit = false)
  public void listBranchesOfEmptyProject() throws Exception {
    assertBranches(ImmutableList.of(
          branch("HEAD", null, false),
          branch("refs/meta/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();
    assertBranches(ImmutableList.of(
          branch("HEAD", "master", false),
          branch("refs/meta/config",  null, false),
          branch("refs/heads/dev", dev, true),
          branch("refs/heads/master", master, false)),
        list().get());
  }

  @Test
  public void listBranchesSomeHidden() throws Exception {
    blockRead(project, "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
    assertBranches(ImmutableList.of(
          branch("HEAD", "master", false),
          branch("refs/heads/master", master, false)),
        list().get());
  }

  @Test
  public void listBranchesHeadHidden() throws Exception {
    blockRead(project, "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
    assertBranches(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",
          "refs/meta/config",
          "refs/heads/master",
          "refs/heads/someBranch1"),
        list().withLimit(4).get());

    // Limit higher than total number of branches.
    assertRefNames(ImmutableList.of(
          "HEAD",
          "refs/meta/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());

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

  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;
  }
}
