// 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.server.change;

import static com.google.common.truth.Truth.assertThat;
import static com.google.inject.Scopes.SINGLETON;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.junit.Assert.fail;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.CommentRange;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.PatchLineCommentAccess;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.account.FakeRealm;
import com.google.gerrit.server.account.GroupBackend;
import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.AnonymousCowardNameProvider;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.DisableReverseDnsLookup;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitModule;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.testutil.ConfigSuite;
import com.google.gerrit.testutil.FakeAccountCache;
import com.google.gerrit.testutil.InMemoryRepositoryManager;
import com.google.gerrit.testutil.TestChanges;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.util.Providers;

import org.easymock.IAnswer;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

@RunWith(ConfigSuite.class)
public class CommentsTest  {
  private static final TimeZone TZ =
      TimeZone.getTimeZone("America/Los_Angeles");

  @ConfigSuite.Parameter
  public Config config;

  @ConfigSuite.Config
  public static @GerritServerConfig Config noteDbEnabled() {
    return NotesMigration.allEnabledConfig();
  }

  private Injector injector;
  private ReviewDb db;
  private Project.NameKey project;
  private Account.Id ownerId;
  private RevisionResource revRes1;
  private RevisionResource revRes2;
  private RevisionResource revRes3;
  private PatchLineComment plc1;
  private PatchLineComment plc2;
  private PatchLineComment plc3;
  private PatchLineComment plc4;
  private PatchLineComment plc5;
  private PatchLineComment plc6;
  private IdentifiedUser changeOwner;

  @Inject private AllUsersNameProvider allUsers;
  @Inject private Comments comments;
  @Inject private DraftComments drafts;
  @Inject private GetComment getComment;
  @Inject private IdentifiedUser.GenericFactory userFactory;
  @Inject private InMemoryRepositoryManager repoManager;
  @Inject private NotesMigration migration;
  @Inject private PatchLineCommentsUtil plcUtil;

  @Before
  public void setUp() throws Exception {
    @SuppressWarnings("unchecked")
    final DynamicMap<RestView<CommentResource>> commentViews =
        createMock(DynamicMap.class);
    final TypeLiteral<DynamicMap<RestView<CommentResource>>> commentViewsType =
        new TypeLiteral<DynamicMap<RestView<CommentResource>>>() {};
    @SuppressWarnings("unchecked")
    final DynamicMap<RestView<DraftCommentResource>> draftViews =
        createMock(DynamicMap.class);
    final TypeLiteral<DynamicMap<RestView<DraftCommentResource>>> draftViewsType =
        new TypeLiteral<DynamicMap<RestView<DraftCommentResource>>>() {};

    final AccountLoader.Factory alf =
        createMock(AccountLoader.Factory.class);
    db = createMock(ReviewDb.class);
    final FakeAccountCache accountCache = new FakeAccountCache();
    final PersonIdent serverIdent = new PersonIdent(
        "Gerrit Server", "noreply@gerrit.com", TimeUtil.nowTs(), TZ);
    project = new Project.NameKey("test-project");

    Account co = new Account(new Account.Id(1), TimeUtil.nowTs());
    co.setFullName("Change Owner");
    co.setPreferredEmail("change@owner.com");
    accountCache.put(co);
    ownerId = co.getId();

    Account ou = new Account(new Account.Id(2), TimeUtil.nowTs());
    ou.setFullName("Other Account");
    ou.setPreferredEmail("other@account.com");
    accountCache.put(ou);
    Account.Id otherUserId = ou.getId();

    AbstractModule mod = new AbstractModule() {
      @Override
      protected void configure() {
        bind(commentViewsType).toInstance(commentViews);
        bind(draftViewsType).toInstance(draftViews);
        bind(AccountLoader.Factory.class).toInstance(alf);
        bind(ReviewDb.class).toInstance(db);
        bind(Realm.class).to(FakeRealm.class);
        bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(config);
        bind(ProjectCache.class).toProvider(Providers.<ProjectCache> of(null));
        install(new GitModule());
        bind(GitRepositoryManager.class).to(InMemoryRepositoryManager.class);
        bind(InMemoryRepositoryManager.class)
            .toInstance(new InMemoryRepositoryManager());
        bind(CapabilityControl.Factory.class)
            .toProvider(Providers.<CapabilityControl.Factory> of(null));
        bind(String.class).annotatedWith(AnonymousCowardName.class)
            .toProvider(AnonymousCowardNameProvider.class);
        bind(String.class).annotatedWith(CanonicalWebUrl.class)
            .toInstance("http://localhost:8080/");
        bind(Boolean.class).annotatedWith(DisableReverseDnsLookup.class)
            .toInstance(Boolean.FALSE);
        bind(GroupBackend.class).to(SystemGroupBackend.class).in(SINGLETON);
        bind(AccountCache.class).toInstance(accountCache);
        bind(GitReferenceUpdated.class)
            .toInstance(GitReferenceUpdated.DISABLED);
        bind(PersonIdent.class).annotatedWith(GerritPersonIdent.class)
          .toInstance(serverIdent);
      }

      @Provides
      @Singleton
      CurrentUser getCurrentUser(IdentifiedUser.GenericFactory userFactory) {
        return userFactory.create(ownerId);
      }
    };

    injector = Guice.createInjector(mod);
    injector.injectMembers(this);

    repoManager.createRepository(project);
    changeOwner = userFactory.create(ownerId);
    IdentifiedUser otherUser = userFactory.create(otherUserId);

    AccountLoader accountLoader = createMock(AccountLoader.class);
    accountLoader.fill();
    expectLastCall().anyTimes();
    expect(accountLoader.get(ownerId))
        .andReturn(new AccountInfo(ownerId.get())).anyTimes();
    expect(accountLoader.get(otherUserId))
        .andReturn(new AccountInfo(otherUserId.get())).anyTimes();
    expect(alf.create(true)).andReturn(accountLoader).anyTimes();
    replay(accountLoader, alf);

    repoManager.createRepository(allUsers.get());

    PatchLineCommentAccess plca = createMock(PatchLineCommentAccess.class);
    expect(db.patchComments()).andReturn(plca).anyTimes();

    Change change1 = newChange();
    PatchSet.Id psId1 = new PatchSet.Id(change1.getId(), 1);
    PatchSet ps1 = new PatchSet(psId1);
    PatchSet.Id psId2 = new PatchSet.Id(change1.getId(), 2);
    PatchSet ps2 = new PatchSet(psId2);

    Change change2 = newChange();
    PatchSet.Id psId3 = new PatchSet.Id(change2.getId(), 1);
    PatchSet ps3 = new PatchSet(psId3);

    long timeBase = TimeUtil.roundToSecond(TimeUtil.nowTs()).getTime();
    plc1 = newPatchLineComment(psId1, "Comment1", null,
        "FileOne.txt", Side.REVISION, 3, ownerId, timeBase,
        "First Comment", new CommentRange(1, 2, 3, 4));
    plc1.setRevId(new RevId("ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD"));
    plc2 = newPatchLineComment(psId1, "Comment2", "Comment1",
        "FileOne.txt", Side.REVISION, 3, otherUserId, timeBase + 1000,
        "Reply to First Comment",  new CommentRange(1, 2, 3, 4));
    plc2.setRevId(new RevId("ABCDABCDABCDABCDABCDABCDABCDABCDABCDABCD"));
    plc3 = newPatchLineComment(psId1, "Comment3", "Comment1",
        "FileOne.txt", Side.PARENT, 3, ownerId, timeBase + 2000,
        "First Parent Comment",  new CommentRange(1, 2, 3, 4));
    plc3.setRevId(new RevId("CDEFCDEFCDEFCDEFCDEFCDEFCDEFCDEFCDEFCDEF"));
    plc4 = newPatchLineComment(psId2, "Comment4", null, "FileOne.txt",
        Side.REVISION, 3, ownerId, timeBase + 3000, "Second Comment",
        new CommentRange(1, 2, 3, 4), Status.DRAFT);
    plc4.setRevId(new RevId("BCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDE"));
    plc5 = newPatchLineComment(psId2, "Comment5", null, "FileOne.txt",
        Side.REVISION, 5, ownerId, timeBase + 4000, "Third Comment",
        new CommentRange(3, 4, 5, 6), Status.DRAFT);
    plc5.setRevId(new RevId("BCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDE"));
    plc5.setRevId(new RevId("BCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDEBCDE"));
    plc6 = newPatchLineComment(psId3, "Comment6", null, "FileOne.txt",
        Side.REVISION, 5, ownerId, timeBase + 5000, "Sixth Comment",
        new CommentRange(3, 4, 5, 6), Status.DRAFT);
    plc6.setRevId(new RevId("1234123412341234123412341234123412341234"));

    List<PatchLineComment> commentsByOwner = Lists.newArrayList();
    commentsByOwner.add(plc1);
    commentsByOwner.add(plc3);
    List<PatchLineComment> commentsByReviewer = Lists.newArrayList();
    commentsByReviewer.add(plc2);
    List<PatchLineComment> drafts1 = Lists.newArrayList();
    drafts1.add(plc4);
    drafts1.add(plc5);
    List<PatchLineComment> drafts2 = Lists.newArrayList();
    drafts2.add(plc6);

    plca.upsert(commentsByOwner);
    expectLastCall().anyTimes();
    plca.upsert(commentsByReviewer);
    expectLastCall().anyTimes();
    plca.upsert(drafts1);
    expectLastCall().anyTimes();
    plca.upsert(drafts2);
    expectLastCall().anyTimes();

    expect(plca.publishedByPatchSet(psId1))
        .andAnswer(results(plc1, plc2, plc3)).anyTimes();
    expect(plca.publishedByPatchSet(psId2))
        .andAnswer(results()).anyTimes();
    expect(plca.draftByPatchSetAuthor(psId1, ownerId))
        .andAnswer(results()).anyTimes();
    expect(plca.draftByPatchSetAuthor(psId2, ownerId))
        .andAnswer(results(plc4, plc5)).anyTimes();
    expect(plca.byChange(change1.getId()))
        .andAnswer(results(plc1, plc2, plc3, plc4, plc5)).anyTimes();
    expect(plca.draftByAuthor(ownerId))
        .andAnswer(results(plc4, plc5, plc6)).anyTimes();
    replay(db, plca);

    ChangeUpdate update = newUpdate(change1, changeOwner);
    update.setPatchSetId(psId1);
    plcUtil.upsertComments(db, update, commentsByOwner);
    update.commit();

    update = newUpdate(change1, otherUser);
    update.setPatchSetId(psId1);
    plcUtil.upsertComments(db, update, commentsByReviewer);
    update.commit();

    update = newUpdate(change1, changeOwner);
    update.setPatchSetId(psId2);
    plcUtil.upsertComments(db, update, drafts1);
    update.commit();

    update = newUpdate(change2, changeOwner);
    update.setPatchSetId(psId3);
    plcUtil.upsertComments(db, update, drafts2);
    update.commit();

    ChangeControl ctl = stubChangeControl(change1);
    revRes1 = new RevisionResource(new ChangeResource(ctl, null), ps1);
    revRes2 = new RevisionResource(new ChangeResource(ctl, null), ps2);
    revRes3 = new RevisionResource(new ChangeResource(stubChangeControl(change2), null), ps3);
  }

  private ChangeControl stubChangeControl(Change c) throws OrmException {
    return TestChanges.stubChangeControl(
        repoManager, migration, c, allUsers, changeOwner);
  }

  private Change newChange() {
    return TestChanges.newChange(project, changeOwner.getAccountId());
  }

  private ChangeUpdate newUpdate(Change c, final IdentifiedUser user) throws Exception {
    return TestChanges.newUpdate(
        injector, repoManager, migration, c, allUsers, user);
  }

  @Test
  public void testListComments() throws Exception {
    // test ListComments for patch set 1
    assertListComments(revRes1, ImmutableMap.of(
        "FileOne.txt", Lists.newArrayList(plc3, plc1, plc2)));

    // test ListComments for patch set 2
    assertListComments(revRes2,
        Collections.<String, List<PatchLineComment>>emptyMap());
  }

  @Test
  public void testGetComment() throws Exception {
    // test GetComment for existing comment
    assertGetComment(revRes1, plc1, plc1.getKey().get());

    // test GetComment for non-existent comment
    assertGetComment(revRes1, null, "BadComment");
  }

  @Test
  public void testListDrafts() throws Exception {
    // test ListDrafts for patch set 1
    assertListDrafts(revRes1,
        Collections.<String, List<PatchLineComment>> emptyMap());

    // test ListDrafts for patch set 2
    assertListDrafts(revRes2, ImmutableMap.of(
        "FileOne.txt", Lists.newArrayList(plc4, plc5)));
  }

  @Test
  public void testPatchLineCommentsUtilByCommentStatus() throws OrmException {
    assertThat(plcUtil.publishedByChange(db, revRes2.getNotes()))
        .containsExactly(plc1, plc2, plc3).inOrder();
    assertThat(plcUtil.draftByChange(db, revRes2.getNotes()))
        .containsExactly(plc4, plc5).inOrder();
  }

  @Test
  public void testPatchLineCommentsUtilDraftByChangeAuthor() throws Exception {
    assertThat(plcUtil.draftByChangeAuthor(db, revRes1.getNotes(), ownerId))
        .containsExactly(plc4, plc5).inOrder();
    assertThat(plcUtil.draftByChangeAuthor(db, revRes3.getNotes(), ownerId))
        .containsExactly(plc6);
  }

  private static IAnswer<ResultSet<PatchLineComment>> results(
      final PatchLineComment... comments) {
    return new IAnswer<ResultSet<PatchLineComment>>() {
      @Override
      public ResultSet<PatchLineComment> answer() throws Throwable {
        return new ListResultSet<>(Lists.newArrayList(comments));
      }};
  }

  private void assertGetComment(RevisionResource res, PatchLineComment expected,
      String uuid) throws Exception {
    try {
      CommentResource commentRes = comments.parse(res, IdString.fromUrl(uuid));
      if (expected == null) {
        fail("Expected no comment");
      }
      CommentInfo actual = getComment.apply(commentRes);
      assertComment(expected, actual, true);
    } catch (ResourceNotFoundException e) {
      if (expected != null) {
        fail("Expected to find comment");
      }
    }
  }

  private void assertListComments(RevisionResource res,
      Map<String, ? extends List<PatchLineComment>> expected) throws Exception {
    assertCommentMap(comments.list().apply(res), expected, true);
  }

  private void assertListDrafts(RevisionResource res,
      Map<String, ? extends List<PatchLineComment>> expected) throws Exception {
    assertCommentMap(drafts.list().apply(res), expected, false);
  }

  private void assertCommentMap(Map<String, List<CommentInfo>> actual,
      Map<String, ? extends List<PatchLineComment>> expected,
      boolean isPublished) {
    assertThat((Iterable<?>)actual.keySet()).containsExactlyElementsIn(expected.keySet());
    for (Map.Entry<String, List<CommentInfo>> entry : actual.entrySet()) {
      List<CommentInfo> actualList = entry.getValue();
      List<PatchLineComment> expectedList = expected.get(entry.getKey());
      assertThat(actualList).hasSize(expectedList.size());
      for (int i = 0; i < expectedList.size(); i++) {
        assertComment(expectedList.get(i), actualList.get(i), isPublished);
      }
    }
  }

  private static void assertComment(PatchLineComment plc, CommentInfo ci,
      boolean isPublished) {
    assertThat(ci.id).isEqualTo(plc.getKey().get());
    assertThat(ci.inReplyTo).isEqualTo(plc.getParentUuid());
    assertThat(ci.message).isEqualTo(plc.getMessage());
    if (isPublished) {
      assertThat(ci.author).isNotNull();
      assertThat(new Account.Id(ci.author._accountId))
          .isEqualTo(plc.getAuthor());
    }
    assertThat((int) ci.line).isEqualTo(plc.getLine());
    assertThat(MoreObjects.firstNonNull(ci.side, Side.REVISION))
        .isEqualTo(plc.getSide() == 0 ? Side.PARENT : Side.REVISION);
    assertThat(TimeUtil.roundToSecond(ci.updated))
        .isEqualTo(TimeUtil.roundToSecond(plc.getWrittenOn()));
    assertThat(ci.updated).isEqualTo(plc.getWrittenOn());
    assertThat(ci.range.startLine).isEqualTo(plc.getRange().getStartLine());
    assertThat(ci.range.startCharacter)
        .isEqualTo(plc.getRange().getStartCharacter());
    assertThat(ci.range.endLine).isEqualTo(plc.getRange().getEndLine());
    assertThat(ci.range.endCharacter)
        .isEqualTo(plc.getRange().getEndCharacter());
  }

  private static PatchLineComment newPatchLineComment(PatchSet.Id psId,
      String uuid, String inReplyToUuid, String filename, Side side, int line,
      Account.Id authorId, long millis, String message, CommentRange range,
      PatchLineComment.Status status) {
    Patch.Key p = new Patch.Key(psId, filename);
    PatchLineComment.Key id = new PatchLineComment.Key(p, uuid);
    PatchLineComment plc =
        new PatchLineComment(id, line, authorId, inReplyToUuid, TimeUtil.nowTs());
    plc.setMessage(message);
    plc.setRange(range);
    plc.setSide(side == Side.PARENT ? (short) 0 : (short) 1);
    plc.setStatus(status);
    plc.setWrittenOn(new Timestamp(millis));
    return plc;
  }

  private static PatchLineComment newPatchLineComment(PatchSet.Id psId,
      String uuid, String inReplyToUuid, String filename, Side side, int line,
      Account.Id authorId, long millis, String message, CommentRange range) {
    return newPatchLineComment(psId, uuid, inReplyToUuid, filename, side, line,
        authorId, millis, message, range, Status.PUBLISHED);
  }
}
