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

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_HASHTAGS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_LABEL;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_PATCH_SET;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_STATUS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_SUBMITTED_WITH;
import static com.google.gerrit.server.notedb.CommentsInNotesUtil.getCommentPsId;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.gerrit.common.data.SubmitRecord;
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.Project;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.util.LabelVote;
import com.google.gwtorm.server.OrmException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;

import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.FooterKey;
import org.eclipse.jgit.revwalk.RevCommit;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * A delta to apply to a change.
 * <p>
 * This delta will become two unique commits: one in the AllUsers repo that will
 * contain the draft comments on this change and one in the notes branch that
 * will contain approvals, reviewers, change status, subject, submit records,
 * the change message, and published comments. There are limitations on the set
 * of modifications that can be handled in a single update. In particular, there
 * is a single author and timestamp for each update.
 * <p>
 * This class is not thread-safe.
 */
public class ChangeUpdate extends AbstractChangeUpdate {
  public interface Factory {
    ChangeUpdate create(ChangeControl ctl);
    ChangeUpdate create(ChangeControl ctl, Date when);
    @VisibleForTesting
    ChangeUpdate create(ChangeControl ctl, Date when,
        Comparator<String> labelNameComparator);
  }

  private final AccountCache accountCache;
  private final Map<String, Optional<Short>> approvals;
  private final Map<Account.Id, ReviewerState> reviewers;
  private Change.Status status;
  private String subject;
  private List<SubmitRecord> submitRecords;
  private final CommentsInNotesUtil commentsUtil;
  private List<PatchLineComment> commentsForBase;
  private List<PatchLineComment> commentsForPs;
  private Set<String> hashtags;
  private String changeMessage;
  private ChangeNotes notes;

  private final ChangeDraftUpdate.Factory draftUpdateFactory;
  private ChangeDraftUpdate draftUpdate;

  @AssistedInject
  private ChangeUpdate(
      @GerritPersonIdent PersonIdent serverIdent,
      @AnonymousCowardName String anonymousCowardName,
      GitRepositoryManager repoManager,
      NotesMigration migration,
      AccountCache accountCache,
      MetaDataUpdate.User updateFactory,
      ChangeDraftUpdate.Factory draftUpdateFactory,
      ProjectCache projectCache,
      @Assisted ChangeControl ctl,
      CommentsInNotesUtil commentsUtil) {
    this(serverIdent, anonymousCowardName, repoManager, migration, accountCache,
        updateFactory, draftUpdateFactory,
        projectCache, ctl, serverIdent.getWhen(), commentsUtil);
  }

  @AssistedInject
  private ChangeUpdate(
      @GerritPersonIdent PersonIdent serverIdent,
      @AnonymousCowardName String anonymousCowardName,
      GitRepositoryManager repoManager,
      NotesMigration migration,
      AccountCache accountCache,
      MetaDataUpdate.User updateFactory,
      ChangeDraftUpdate.Factory draftUpdateFactory,
      ProjectCache projectCache,
      @Assisted ChangeControl ctl,
      @Assisted Date when,
      CommentsInNotesUtil commentsUtil) {
    this(serverIdent, anonymousCowardName, repoManager, migration, accountCache,
        updateFactory, draftUpdateFactory, ctl,
        when,
        projectCache.get(getProjectName(ctl)).getLabelTypes().nameComparator(),
        commentsUtil);
  }

  private static Project.NameKey getProjectName(ChangeControl ctl) {
    return ctl.getChange().getDest().getParentKey();
  }

  @AssistedInject
  private ChangeUpdate(
      @GerritPersonIdent PersonIdent serverIdent,
      @AnonymousCowardName String anonymousCowardName,
      GitRepositoryManager repoManager,
      NotesMigration migration,
      AccountCache accountCache,
      MetaDataUpdate.User updateFactory,
      ChangeDraftUpdate.Factory draftUpdateFactory,
      @Assisted ChangeControl ctl,
      @Assisted Date when,
      @Assisted Comparator<String> labelNameComparator,
      CommentsInNotesUtil commentsUtil) {
    super(migration, repoManager, updateFactory, ctl, serverIdent,
        anonymousCowardName, when);
    this.draftUpdateFactory = draftUpdateFactory;
    this.accountCache = accountCache;
    this.commentsUtil = commentsUtil;
    this.approvals = Maps.newTreeMap(labelNameComparator);
    this.reviewers = Maps.newLinkedHashMap();
    this.commentsForPs = Lists.newArrayList();
    this.commentsForBase = Lists.newArrayList();
  }

  public void setStatus(Change.Status status) {
    checkArgument(status != Change.Status.SUBMITTED,
        "use submit(Iterable<PatchSetApproval>)");
    this.status = status;
  }

  public void putApproval(String label, short value) {
    approvals.put(label, Optional.of(value));
  }

  public void removeApproval(String label) {
    approvals.put(label, Optional.<Short> absent());
  }

  public void submit(Iterable<SubmitRecord> submitRecords) {
    status = Change.Status.SUBMITTED;
    this.submitRecords = ImmutableList.copyOf(submitRecords);
    checkArgument(!this.submitRecords.isEmpty(),
        "no submit records specified at submit time");
  }

  public void setSubject(String subject) {
    this.subject = subject;
  }

  public void setChangeMessage(String changeMessage) {
    this.changeMessage = changeMessage;
  }

  public void insertComment(PatchLineComment comment) throws OrmException {
    if (comment.getStatus() == Status.DRAFT) {
      insertDraftComment(comment);
    } else {
      insertPublishedComment(comment);
    }
  }

  public void upsertComment(PatchLineComment comment) throws OrmException {
    if (comment.getStatus() == Status.DRAFT) {
      upsertDraftComment(comment);
    } else {
      deleteDraftCommentIfPresent(comment);
      upsertPublishedComment(comment);
    }
  }

  public void updateComment(PatchLineComment comment) throws OrmException {
    if (comment.getStatus() == Status.DRAFT) {
      updateDraftComment(comment);
    } else {
      deleteDraftCommentIfPresent(comment);
      updatePublishedComment(comment);
    }
  }

  public void deleteComment(PatchLineComment comment) throws OrmException {
    if (comment.getStatus() == Status.DRAFT) {
      deleteDraftComment(comment);
    } else {
      throw new IllegalArgumentException("Cannot delete a published comment.");
    }
  }

  private void insertPublishedComment(PatchLineComment c) throws OrmException {
    verifyComment(c);
    if (notes == null) {
      notes = getChangeNotes().load();
    }
    if (migration.readChanges()) {
      checkArgument(!notes.containsComment(c),
          "A comment already exists with the same key as the following comment,"
          + " so we cannot insert this comment: %s", c);
    }
    if (c.getSide() == 0) {
      commentsForBase.add(c);
    } else {
      commentsForPs.add(c);
    }
  }

  private void insertDraftComment(PatchLineComment c) throws OrmException {
    createDraftUpdateIfNull(c);
    draftUpdate.insertComment(c);
  }

  private void upsertPublishedComment(PatchLineComment c) throws OrmException {
    verifyComment(c);
    if (notes == null) {
      notes = getChangeNotes().load();
    }
    // This could allow callers to update a published comment if migration.write
    // is on and migration.readComments is off because we will not be able to
    // verify that the comment didn't already exist as a published comment
    // since we don't have a ReviewDb.
    if (migration.readChanges()) {
      checkArgument(!notes.containsCommentPublished(c),
          "Cannot update a comment that has already been published and saved");
    }
    if (c.getSide() == 0) {
      commentsForBase.add(c);
    } else {
      commentsForPs.add(c);
    }
  }

  private void upsertDraftComment(PatchLineComment c) {
    createDraftUpdateIfNull(c);
    draftUpdate.upsertComment(c);
  }

  private void updatePublishedComment(PatchLineComment c) throws OrmException {
    verifyComment(c);
    if (notes == null) {
      notes = getChangeNotes().load();
    }
    // See comment above in upsertPublishedComment() about potential risk with
    // this check.
    if (migration.readChanges()) {
      checkArgument(!notes.containsCommentPublished(c),
          "Cannot update a comment that has already been published and saved");
    }
    if (c.getSide() == 0) {
      commentsForBase.add(c);
    } else {
      commentsForPs.add(c);
    }
  }

  private void updateDraftComment(PatchLineComment c) throws OrmException {
    createDraftUpdateIfNull(c);
    draftUpdate.updateComment(c);
  }

  private void deleteDraftComment(PatchLineComment c) throws OrmException {
    createDraftUpdateIfNull(c);
    draftUpdate.deleteComment(c);
  }

  private void deleteDraftCommentIfPresent(PatchLineComment c)
      throws OrmException {
    createDraftUpdateIfNull(c);
    draftUpdate.deleteCommentIfPresent(c);
  }

  private void createDraftUpdateIfNull(PatchLineComment c) {
    if (draftUpdate == null) {
      draftUpdate = draftUpdateFactory.create(ctl, when);
      if (psId != null) {
        draftUpdate.setPatchSetId(psId);
      } else {
        draftUpdate.setPatchSetId(getCommentPsId(c));
      }
    }
  }

  private void verifyComment(PatchLineComment c) {
    checkArgument(psId != null,
        "setPatchSetId must be called first");
    checkArgument(getCommentPsId(c).equals(psId),
        "Comment on %s doesn't match previous patch set %s",
        getCommentPsId(c), psId);
    checkArgument(c.getRevId() != null);
    checkArgument(c.getStatus() == Status.PUBLISHED,
        "Cannot add a draft comment to a ChangeUpdate. Use a ChangeDraftUpdate"
        + " for draft comments");
    checkArgument(c.getAuthor().equals(getUser().getAccountId()),
        "The author for the following comment does not match the author of"
        + " this ChangeDraftUpdate (%s): %s", getUser().getAccountId(), c);

  }

  public void setHashtags(Set<String> hashtags) {
    this.hashtags = hashtags;
  }

  public void putReviewer(Account.Id reviewer, ReviewerState type) {
    checkArgument(type != ReviewerState.REMOVED, "invalid ReviewerType");
    reviewers.put(reviewer, type);
  }

  public void removeReviewer(Account.Id reviewer) {
    reviewers.put(reviewer, ReviewerState.REMOVED);
  }

  /** @return the tree id for the updated tree */
  private ObjectId storeCommentsInNotes() throws OrmException, IOException {
    ChangeNotes notes = ctl.getNotes().load();
    NoteMap noteMap = notes.getNoteMap();
    if (noteMap == null) {
      noteMap = NoteMap.newEmptyMap();
    }
    if (commentsForPs.isEmpty() && commentsForBase.isEmpty()) {
      return null;
    }

    Multimap<PatchSet.Id, PatchLineComment> allCommentsOnBases =
        notes.getBaseComments();
    Multimap<PatchSet.Id, PatchLineComment> allCommentsOnPs =
        notes.getPatchSetComments();

    // This writes all comments for the base of this PS to the note map.
    if (!commentsForBase.isEmpty()) {
      List<PatchLineComment> baseCommentsForThisPs =
          new ArrayList<>(allCommentsOnBases.get(psId));
      baseCommentsForThisPs.addAll(commentsForBase);
      commentsUtil.writeCommentsToNoteMap(noteMap, baseCommentsForThisPs,
          inserter);
    }

    // This write all comments for this PS to the note map.
    if (!commentsForPs.isEmpty()) {
      List<PatchLineComment> commentsForThisPs =
          new ArrayList<>(allCommentsOnPs.get(psId));
      commentsForThisPs.addAll(commentsForPs);
      commentsUtil.writeCommentsToNoteMap(noteMap, commentsForThisPs, inserter);
    }
    return noteMap.writeTree(inserter);
  }

  public RevCommit commit() throws IOException {
    BatchMetaDataUpdate batch = openUpdate();
    try {
      writeCommit(batch);
      if (draftUpdate != null) {
        draftUpdate.commit();
      }
      RevCommit c = batch.commit();
      return c;
    } catch (OrmException e) {
      throw new IOException(e);
    } finally {
      batch.close();
    }
  }

  @Override
  public void writeCommit(BatchMetaDataUpdate batch) throws OrmException,
      IOException {
    CommitBuilder builder = new CommitBuilder();
    if (migration.writeChanges()) {
      ObjectId treeId = storeCommentsInNotes();
      if (treeId != null) {
        builder.setTreeId(treeId);
      }
    }
    batch.write(this, builder);
  }

  @Override
  protected String getRefName() {
    return ChangeNoteUtil.changeRefName(getChange().getId());
  }

  @Override
  protected boolean onSave(CommitBuilder commit) {
    if (isEmpty()) {
      return false;
    }
    commit.setAuthor(newIdent(getUser().getAccount(), when));
    commit.setCommitter(new PersonIdent(serverIdent, when));

    int ps = psId != null ? psId.get() : getChange().currentPatchSetId().get();
    StringBuilder msg = new StringBuilder();
    if (subject != null) {
      msg.append(subject);
    } else {
      msg.append("Update patch set ").append(ps);
    }
    msg.append("\n\n");

    if (changeMessage != null) {
      msg.append(changeMessage);
      msg.append("\n\n");
    }


    addFooter(msg, FOOTER_PATCH_SET, ps);
    if (status != null) {
      addFooter(msg, FOOTER_STATUS, status.name().toLowerCase());
    }

    if (hashtags != null) {
      addFooter(msg, FOOTER_HASHTAGS, Joiner.on(",").join(hashtags));
    }

    for (Map.Entry<Account.Id, ReviewerState> e : reviewers.entrySet()) {
      Account account = accountCache.get(e.getKey()).getAccount();
      PersonIdent ident = newIdent(account, when);
      addFooter(msg, e.getValue().getFooterKey())
          .append(ident.getName())
          .append(" <").append(ident.getEmailAddress()).append(">\n");
    }

    for (Map.Entry<String, Optional<Short>> e : approvals.entrySet()) {
      if (!e.getValue().isPresent()) {
        addFooter(msg, FOOTER_LABEL, '-', e.getKey());
      } else {
        addFooter(msg, FOOTER_LABEL, LabelVote.create(
            e.getKey(), e.getValue().get()).formatWithEquals());
      }
    }

    if (submitRecords != null) {
      for (SubmitRecord rec : submitRecords) {
        addFooter(msg, FOOTER_SUBMITTED_WITH)
            .append(rec.status);
        if (rec.errorMessage != null) {
          msg.append(' ').append(sanitizeFooter(rec.errorMessage));
        }
        msg.append('\n');

        if (rec.labels != null) {
          for (SubmitRecord.Label label : rec.labels) {
            addFooter(msg, FOOTER_SUBMITTED_WITH)
                .append(label.status).append(": ").append(label.label);
            if (label.appliedBy != null) {
              PersonIdent ident =
                  newIdent(accountCache.get(label.appliedBy).getAccount(), when);
              msg.append(": ").append(ident.getName())
                  .append(" <").append(ident.getEmailAddress()).append('>');
            }
            msg.append('\n');
          }
        }
      }
    }

    commit.setMessage(msg.toString());
    return true;
  }

  @Override
  protected Project.NameKey getProjectName() {
    return getProjectName(ctl);
  }

  private boolean isEmpty() {
    return approvals.isEmpty()
        && changeMessage == null
        && commentsForBase.isEmpty()
        && commentsForPs.isEmpty()
        && reviewers.isEmpty()
        && status == null
        && subject == null
        && submitRecords == null
        && hashtags == null;
  }

  private static StringBuilder addFooter(StringBuilder sb, FooterKey footer) {
    return sb.append(footer.getName()).append(": ");
  }

  private static void addFooter(StringBuilder sb, FooterKey footer,
      Object... values) {
    addFooter(sb, footer);
    for (Object value : values) {
      sb.append(value);
    }
    sb.append('\n');
  }

  private static String sanitizeFooter(String value) {
    return value.replace('\n', ' ').replace('\0', ' ');
  }
}
