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

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
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.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.DraftCommentNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.PatchList;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;

/**
 * Utility functions to manipulate PatchLineComments.
 * <p>
 * These methods either query for and update PatchLineComments in the NoteDb or
 * ReviewDb, depending on the state of the NotesMigration.
 */
@Singleton
public class PatchLineCommentsUtil {
  private final GitRepositoryManager repoManager;
  private final AllUsersName allUsers;
  private final DraftCommentNotes.Factory draftFactory;
  private final NotesMigration migration;

  @VisibleForTesting
  @Inject
  public PatchLineCommentsUtil(GitRepositoryManager repoManager,
      AllUsersNameProvider allUsersProvider,
      DraftCommentNotes.Factory draftFactory,
      NotesMigration migration) {
    this.repoManager = repoManager;
    this.allUsers = allUsersProvider.get();
    this.draftFactory = draftFactory;
    this.migration = migration;
  }

  public Optional<PatchLineComment> get(ReviewDb db, ChangeNotes notes,
      PatchLineComment.Key key) throws OrmException {
    if (!migration.readChanges()) {
      return Optional.fromNullable(db.patchComments().get(key));
    }
    for (PatchLineComment c : publishedByChange(db, notes)) {
      if (key.equals(c.getKey())) {
        return Optional.of(c);
      }
    }
    for (PatchLineComment c : draftByChange(db, notes)) {
      if (key.equals(c.getKey())) {
        return Optional.of(c);
      }
    }
    return Optional.absent();
  }

  public List<PatchLineComment> publishedByChange(ReviewDb db,
      ChangeNotes notes) throws OrmException {
    if (!migration.readChanges()) {
      return sort(byCommentStatus(
          db.patchComments().byChange(notes.getChangeId()), Status.PUBLISHED));
    }

    notes.load();
    List<PatchLineComment> comments = Lists.newArrayList();
    comments.addAll(notes.getBaseComments().values());
    comments.addAll(notes.getPatchSetComments().values());
    return sort(comments);
  }

  public List<PatchLineComment> draftByChange(ReviewDb db,
      ChangeNotes notes) throws OrmException {
    if (!migration.readChanges()) {
      return sort(byCommentStatus(
          db.patchComments().byChange(notes.getChangeId()), Status.DRAFT));
    }

    List<PatchLineComment> comments = Lists.newArrayList();
    Iterable<String> filtered = getDraftRefs(notes.getChangeId());
    for (String refName : filtered) {
      Account.Id account = Account.Id.fromRefPart(refName);
      if (account != null) {
        comments.addAll(draftByChangeAuthor(db, notes, account));
      }
    }
    return sort(comments);
  }

  private static List<PatchLineComment> byCommentStatus(
      ResultSet<PatchLineComment> comments,
      final PatchLineComment.Status status) {
    return Lists.newArrayList(
      Iterables.filter(comments, new Predicate<PatchLineComment>() {
        @Override
        public boolean apply(PatchLineComment input) {
          return (input.getStatus() == status);
        }
      })
    );
  }

  public List<PatchLineComment> byPatchSet(ReviewDb db,
      ChangeNotes notes, PatchSet.Id psId) throws OrmException {
    if (!migration.readChanges()) {
      return sort(db.patchComments().byPatchSet(psId).toList());
    }
    List<PatchLineComment> comments = Lists.newArrayList();
    comments.addAll(publishedByPatchSet(db, notes, psId));

    Iterable<String> filtered = getDraftRefs(notes.getChangeId());
    for (String refName : filtered) {
      Account.Id account = Account.Id.fromRefPart(refName);
      if (account != null) {
        comments.addAll(draftByPatchSetAuthor(db, psId, account, notes));
      }
    }
    return sort(comments);
  }

  public List<PatchLineComment> publishedByChangeFile(ReviewDb db,
      ChangeNotes notes, Change.Id changeId, String file) throws OrmException {
    if (!migration.readChanges()) {
      return sort(
          db.patchComments().publishedByChangeFile(changeId, file).toList());
    }
    notes.load();
    List<PatchLineComment> comments = Lists.newArrayList();

    addCommentsOnFile(comments, notes.getBaseComments().values(), file);
    addCommentsOnFile(comments, notes.getPatchSetComments().values(),
        file);
    return sort(comments);
  }

  public List<PatchLineComment> publishedByPatchSet(ReviewDb db,
      ChangeNotes notes, PatchSet.Id psId) throws OrmException {
    if (!migration.readChanges()) {
      return sort(
          db.patchComments().publishedByPatchSet(psId).toList());
    }
    notes.load();
    List<PatchLineComment> comments = new ArrayList<>();
    comments.addAll(notes.getPatchSetComments().get(psId));
    comments.addAll(notes.getBaseComments().get(psId));
    return sort(comments);
  }

  public List<PatchLineComment> draftByPatchSetAuthor(ReviewDb db,
      PatchSet.Id psId, Account.Id author, ChangeNotes notes)
      throws OrmException {
    if (!migration.readChanges()) {
      return sort(
          db.patchComments().draftByPatchSetAuthor(psId, author).toList());
    }

    List<PatchLineComment> comments = Lists.newArrayList();
    comments.addAll(notes.getDraftBaseComments(author).row(psId).values());
    comments.addAll(notes.getDraftPsComments(author).row(psId).values());
    return sort(comments);
  }

  public List<PatchLineComment> draftByChangeFileAuthor(ReviewDb db,
      ChangeNotes notes, String file, Account.Id author)
      throws OrmException {
    if (!migration.readChanges()) {
      return sort(
          db.patchComments()
            .draftByChangeFileAuthor(notes.getChangeId(), file, author)
            .toList());
    }
    List<PatchLineComment> comments = Lists.newArrayList();
    addCommentsOnFile(comments, notes.getDraftBaseComments(author).values(),
        file);
    addCommentsOnFile(comments, notes.getDraftPsComments(author).values(),
        file);
    return sort(comments);
  }

  public List<PatchLineComment> draftByChangeAuthor(ReviewDb db,
      ChangeNotes notes, Account.Id author)
      throws OrmException {
    if (!migration.readChanges()) {
      final Change.Id matchId = notes.getChangeId();
      return FluentIterable
          .from(db.patchComments().draftByAuthor(author))
          .filter(new Predicate<PatchLineComment>() {
            @Override
            public boolean apply(PatchLineComment in) {
              Change.Id changeId =
                  in.getKey().getParentKey().getParentKey().getParentKey();
              return changeId.equals(matchId);
            }
          }).toSortedList(ChangeNotes.PLC_ORDER);
    }
    List<PatchLineComment> comments = Lists.newArrayList();
    comments.addAll(notes.getDraftBaseComments(author).values());
    comments.addAll(notes.getDraftPsComments(author).values());
    return sort(comments);
  }

  public List<PatchLineComment> draftByAuthor(ReviewDb db,
      Account.Id author) throws OrmException {
    if (!migration.readChanges()) {
      return sort(db.patchComments().draftByAuthor(author).toList());
    }

    Set<String> refNames =
        getRefNamesAllUsers(RefNames.REFS_DRAFT_COMMENTS);

    List<PatchLineComment> comments = Lists.newArrayList();
    for (String refName : refNames) {
      Account.Id id = Account.Id.fromRefPart(refName);
      if (!author.equals(id)) {
        continue;
      }
      Change.Id changeId = Change.Id.parse(refName);
      DraftCommentNotes draftNotes =
          draftFactory.create(changeId, author).load();
      comments.addAll(draftNotes.getDraftBaseComments().values());
      comments.addAll(draftNotes.getDraftPsComments().values());
    }
    return sort(comments);
  }

  public void insertComments(ReviewDb db, ChangeUpdate update,
      Iterable<PatchLineComment> comments) throws OrmException {
    for (PatchLineComment c : comments) {
      update.insertComment(c);
    }
    db.patchComments().insert(comments);
  }

  public void upsertComments(ReviewDb db, ChangeUpdate update,
      Iterable<PatchLineComment> comments) throws OrmException {
    for (PatchLineComment c : comments) {
      update.upsertComment(c);
    }
    db.patchComments().upsert(comments);
  }

  public void updateComments(ReviewDb db, ChangeUpdate update,
      Iterable<PatchLineComment> comments) throws OrmException {
    for (PatchLineComment c : comments) {
      update.updateComment(c);
    }
    db.patchComments().update(comments);
  }

  public void deleteComments(ReviewDb db, ChangeUpdate update,
      Iterable<PatchLineComment> comments) throws OrmException {
    for (PatchLineComment c : comments) {
      update.deleteComment(c);
    }
    db.patchComments().delete(comments);
  }

  private static Collection<PatchLineComment> addCommentsOnFile(
      Collection<PatchLineComment> commentsOnFile,
      Collection<PatchLineComment> allComments,
      String file) {
    for (PatchLineComment c : allComments) {
      String currentFilename = c.getKey().getParentKey().getFileName();
      if (currentFilename.equals(file)) {
        commentsOnFile.add(c);
      }
    }
    return commentsOnFile;
  }

  public static void setCommentRevId(PatchLineComment c,
      PatchListCache cache, Change change, PatchSet ps) throws OrmException {
    if (c.getRevId() != null) {
      return;
    }
    PatchList patchList;
    try {
      patchList = cache.get(change, ps);
    } catch (PatchListNotAvailableException e) {
      throw new OrmException(e);
    }
    c.setRevId((c.getSide() == (short) 0)
      ? new RevId(ObjectId.toString(patchList.getOldId()))
      : new RevId(ObjectId.toString(patchList.getNewId())));
  }

  private Set<String> getRefNamesAllUsers(String prefix) throws OrmException {
    Repository repo;
    try {
      repo = repoManager.openRepository(allUsers);
    } catch (IOException e) {
      throw new OrmException(e);
    }
    try {
      RefDatabase refDb = repo.getRefDatabase();
      return refDb.getRefs(prefix).keySet();
    } catch (IOException e) {
      throw new OrmException(e);
    } finally {
      repo.close();
    }
  }

  private Iterable<String> getDraftRefs(final Change.Id changeId)
      throws OrmException {
    Set<String> refNames = getRefNamesAllUsers(RefNames.REFS_DRAFT_COMMENTS);
    final String suffix = "-" + changeId.get();
    return Iterables.filter(refNames, new Predicate<String>() {
      @Override
      public boolean apply(String input) {
        return input.endsWith(suffix);
      }
    });
  }

  private static List<PatchLineComment> sort(List<PatchLineComment> comments) {
    Collections.sort(comments, ChangeNotes.PLC_ORDER);
    return comments;
  }
}
