// Copyright (C) 2018 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.extensions.webui;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.verify;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.entities.Account;
import com.google.gerrit.extensions.api.access.CoreOrPluginProjectPermission;
import com.google.gerrit.extensions.conditions.BooleanCondition;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.GroupMembership;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.ForProject;
import com.google.gerrit.server.permissions.PermissionBackend.ForRef;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.permissions.PermissionBackendCondition;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.permissions.ProjectPermission;
import java.util.Collection;
import java.util.Set;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.junit.Test;

public class UiActionsTest {

  private static class FakeForProject extends ForProject {
    private boolean allowValueQueries = true;

    @Override
    public String resourcePath() {
      return "/projects/test-project";
    }

    @Override
    public ForRef ref(String ref) {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public void check(CoreOrPluginProjectPermission perm)
        throws AuthException, PermissionBackendException {
      throw new UnsupportedOperationException("not implemented");
    }

    @Override
    public <T extends CoreOrPluginProjectPermission> Set<T> test(Collection<T> permSet)
        throws PermissionBackendException {
      assertThat(allowValueQueries).isTrue();
      Set<T> ok = Sets.newHashSetWithExpectedSize(permSet.size());
      for (T perm : permSet) {
        // Allow ProjectPermission.READ, if it was requested in the input permSet. This implies
        // that permSet has type Collection<ProjectPermission>, otherwise no permission would
        // compare equal to READ.
        if (perm.equals(ProjectPermission.READ)) {
          ok.add(perm);
        }
      }
      return ok;
    }

    @Override
    public BooleanCondition testCond(CoreOrPluginProjectPermission perm) {
      return new PermissionBackendCondition.ForProject(this, perm, fakeUser());
    }

    @Override
    public Collection<Ref> filter(Collection<Ref> refs, Repository repo, RefFilterOptions opts)
        throws PermissionBackendException {
      throw new UnsupportedOperationException("not implemented");
    }

    private void disallowValueQueries() {
      allowValueQueries = false;
    }

    private static CurrentUser fakeUser() {
      return new CurrentUser() {
        @Override
        public GroupMembership getEffectiveGroups() {
          throw new UnsupportedOperationException("not implemented");
        }

        @Override
        public Object getCacheKey() {
          return new Object();
        }

        @Override
        public boolean isIdentifiedUser() {
          return true;
        }

        @Override
        public Account.Id getAccountId() {
          return Account.id(1);
        }
      };
    }
  }

  @Test
  public void permissionBackendConditionEvaluationDeduplicatesAndBackfills() throws Exception {
    FakeForProject forProject = new FakeForProject();

    // Create three conditions, two of which are identical
    PermissionBackendCondition cond1 =
        (PermissionBackendCondition) forProject.testCond(ProjectPermission.CREATE_CHANGE);
    PermissionBackendCondition cond2 =
        (PermissionBackendCondition) forProject.testCond(ProjectPermission.READ);
    PermissionBackendCondition cond3 =
        (PermissionBackendCondition) forProject.testCond(ProjectPermission.CREATE_CHANGE);

    // Set up the Mock to expect a call of bulkEvaluateTest to only contain cond{1,2} since cond3
    // needs to be identified as duplicate and not called out explicitly.
    PermissionBackend permissionBackendMock = mock(PermissionBackend.class);

    UiActions.evaluatePermissionBackendConditions(
        permissionBackendMock, ImmutableList.of(cond1, cond2, cond3));

    // Disallow queries for value to ensure that cond3 (previously left behind) is backfilled with
    // the value of cond1 and issues no additional call to PermissionBackend.
    forProject.disallowValueQueries();

    verify(permissionBackendMock, only()).bulkEvaluateTest(ImmutableSet.of(cond1, cond2));

    // Assert the values of all conditions
    assertThat(cond1.value()).isFalse();
    assertThat(cond2.value()).isTrue();
    assertThat(cond3.value()).isFalse();
  }
}
