// Copyright (C) 2014 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 static com.google.gerrit.common.data.Permission.forLabel;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.testing.Util.allow;
import static com.google.gerrit.server.project.testing.Util.category;
import static com.google.gerrit.server.project.testing.Util.value;
import static org.junit.Assert.assertEquals;

import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.extensions.api.GerritApi;
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.common.ChangeInput;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.change.LabelNormalizer.Result;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.testing.InMemoryModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import java.util.List;
import org.eclipse.jgit.lib.Repository;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/** Unit tests for {@link LabelNormalizer}. */
public class LabelNormalizerTest {
  @Inject private AccountManager accountManager;
  @Inject private AllProjectsName allProjects;
  @Inject private GitRepositoryManager repoManager;
  @Inject private IdentifiedUser.GenericFactory userFactory;
  @Inject private LabelNormalizer norm;
  @Inject private MetaDataUpdate.User metaDataUpdateFactory;
  @Inject private ProjectCache projectCache;
  @Inject private SchemaCreator schemaCreator;
  @Inject protected ThreadLocalRequestContext requestContext;
  @Inject private ChangeNotes.Factory changeNotesFactory;
  @Inject private ProjectConfig.Factory projectConfigFactory;
  @Inject private GerritApi gApi;

  private LifecycleManager lifecycle;
  private Account.Id userId;
  private IdentifiedUser user;
  private Change change;
  private ChangeNotes notes;

  @Before
  public void setUpInjector() throws Exception {
    Injector injector = Guice.createInjector(new InMemoryModule());
    injector.injectMembers(this);
    lifecycle = new LifecycleManager();
    lifecycle.add(injector);
    lifecycle.start();

    schemaCreator.create();
    userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
    user = userFactory.create(userId);

    requestContext.setContext(() -> user);

    configureProject();
    setUpChange();
  }

  private void configureProject() throws Exception {
    ProjectConfig pc = loadAllProjects();
    for (AccessSection sec : pc.getAccessSections()) {
      for (String label : pc.getLabelSections().keySet()) {
        sec.removePermission(forLabel(label));
      }
    }
    LabelType lt =
        category("Verified", value(1, "Verified"), value(0, "No score"), value(-1, "Fails"));
    pc.getLabelSections().put(lt.getName(), lt);
    save(pc);
  }

  private void setUpChange() throws Exception {
    ChangeInput input = new ChangeInput();
    input.project = allProjects.get();
    input.branch = "master";
    input.newBranch = true;
    input.subject = "Test change";
    ChangeInfo info = gApi.changes().create(input).get();
    notes = changeNotesFactory.createChecked(allProjects, Change.id(info._number));
    change = notes.getChange();
  }

  @After
  public void tearDown() {
    if (lifecycle != null) {
      lifecycle.stop();
    }
    requestContext.setContext(null);
  }

  @Test
  public void noNormalizeByPermission() throws Exception {
    ProjectConfig pc = loadAllProjects();
    allow(pc, forLabel("Code-Review"), -1, 1, REGISTERED_USERS, "refs/heads/*");
    allow(pc, forLabel("Verified"), -1, 1, REGISTERED_USERS, "refs/heads/*");
    save(pc);

    PatchSetApproval cr = psa(userId, "Code-Review", 2);
    PatchSetApproval v = psa(userId, "Verified", 1);
    assertEquals(Result.create(list(cr, v), list(), list()), norm.normalize(notes, list(cr, v)));
  }

  @Test
  public void normalizeByType() throws Exception {
    ProjectConfig pc = loadAllProjects();
    allow(pc, forLabel("Code-Review"), -5, 5, REGISTERED_USERS, "refs/heads/*");
    allow(pc, forLabel("Verified"), -5, 5, REGISTERED_USERS, "refs/heads/*");
    save(pc);

    PatchSetApproval cr = psa(userId, "Code-Review", 5);
    PatchSetApproval v = psa(userId, "Verified", 5);
    assertEquals(
        Result.create(list(), list(copy(cr, 2), copy(v, 1)), list()),
        norm.normalize(notes, list(cr, v)));
  }

  @Test
  public void emptyPermissionRangeKeepsResult() throws Exception {
    PatchSetApproval cr = psa(userId, "Code-Review", 1);
    PatchSetApproval v = psa(userId, "Verified", 1);
    assertEquals(Result.create(list(cr, v), list(), list()), norm.normalize(notes, list(cr, v)));
  }

  @Test
  public void explicitZeroVoteOnNonEmptyRangeIsPresent() throws Exception {
    ProjectConfig pc = loadAllProjects();
    allow(pc, forLabel("Code-Review"), -1, 1, REGISTERED_USERS, "refs/heads/*");
    save(pc);

    PatchSetApproval cr = psa(userId, "Code-Review", 0);
    PatchSetApproval v = psa(userId, "Verified", 0);
    assertEquals(Result.create(list(cr, v), list(), list()), norm.normalize(notes, list(cr, v)));
  }

  private ProjectConfig loadAllProjects() throws Exception {
    try (Repository repo = repoManager.openRepository(allProjects)) {
      ProjectConfig pc = projectConfigFactory.create(allProjects);
      pc.load(repo);
      return pc;
    }
  }

  private void save(ProjectConfig pc) throws Exception {
    try (MetaDataUpdate md = metaDataUpdateFactory.create(pc.getProject().getNameKey(), user)) {
      pc.commit(md);
      projectCache.evict(pc.getProject().getNameKey());
    }
  }

  private PatchSetApproval psa(Account.Id accountId, String label, int value) {
    return PatchSetApproval.builder()
        .key(PatchSetApproval.key(change.currentPatchSetId(), accountId, LabelId.create(label)))
        .value(value)
        .granted(TimeUtil.nowTs())
        .build();
  }

  private PatchSetApproval copy(PatchSetApproval src, int newValue) {
    return src.toBuilder().value(newValue).build();
  }

  private static List<PatchSetApproval> list(PatchSetApproval... psas) {
    return ImmutableList.copyOf(psas);
  }
}
