// 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 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.ListBranchesRequest;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;

import org.junit.Test;

@NoHttpd
public class ListBranchesIT extends AbstractDaemonTest {
  @Test
  public void listBranchesOfNonExistingProject_NotFound() throws Exception {
    try {
      gApi.projects().name("non-existing").branches().get();
      fail("Expected ResourceNotFoundException");
    } catch (ResourceNotFoundException expected) {
      // Expected.
    }
  }

  @Test
  public void listBranchesOfNonVisibleProject_NotFound() throws Exception {
    blockRead(project, "refs/*");
    setApiUser(user);
    try {
      gApi.projects().name(project.get()).branches().get();
      fail("Expected ResourceNotFoundException");
    } catch (ResourceNotFoundException expected) {
      // Expected.
    }
  }

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