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

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.InternalUser;
import com.google.gwtorm.server.OrmException;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.Date;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;

/** A single delta related to a specific patch-set of a change. */
public abstract class AbstractChangeUpdate {
  protected final NotesMigration migration;
  protected final ChangeNoteUtil noteUtil;
  protected final String anonymousCowardName;
  protected final Account.Id accountId;
  protected final Account.Id realAccountId;
  protected final PersonIdent authorIdent;
  protected final Date when;
  private final long readOnlySkewMs;

  @Nullable private final ChangeNotes notes;
  private final Change change;
  protected final PersonIdent serverIdent;

  protected PatchSet.Id psId;
  private ObjectId result;
  protected boolean rootOnly;

  protected AbstractChangeUpdate(
      Config cfg,
      NotesMigration migration,
      ChangeNotes notes,
      CurrentUser user,
      PersonIdent serverIdent,
      String anonymousCowardName,
      ChangeNoteUtil noteUtil,
      Date when) {
    this.migration = migration;
    this.noteUtil = noteUtil;
    this.serverIdent = new PersonIdent(serverIdent, when);
    this.anonymousCowardName = anonymousCowardName;
    this.notes = notes;
    this.change = notes.getChange();
    this.accountId = accountId(user);
    Account.Id realAccountId = accountId(user.getRealUser());
    this.realAccountId = realAccountId != null ? realAccountId : accountId;
    this.authorIdent = ident(noteUtil, serverIdent, anonymousCowardName, user, when);
    this.when = when;
    this.readOnlySkewMs = NoteDbChangeState.getReadOnlySkew(cfg);
  }

  protected AbstractChangeUpdate(
      Config cfg,
      NotesMigration migration,
      ChangeNoteUtil noteUtil,
      PersonIdent serverIdent,
      String anonymousCowardName,
      @Nullable ChangeNotes notes,
      @Nullable Change change,
      Account.Id accountId,
      Account.Id realAccountId,
      PersonIdent authorIdent,
      Date when) {
    checkArgument(
        (notes != null && change == null) || (notes == null && change != null),
        "exactly one of notes or change required");
    this.migration = migration;
    this.noteUtil = noteUtil;
    this.serverIdent = new PersonIdent(serverIdent, when);
    this.anonymousCowardName = anonymousCowardName;
    this.notes = notes;
    this.change = change != null ? change : notes.getChange();
    this.accountId = accountId;
    this.realAccountId = realAccountId;
    this.authorIdent = authorIdent;
    this.when = when;
    this.readOnlySkewMs = NoteDbChangeState.getReadOnlySkew(cfg);
  }

  private static void checkUserType(CurrentUser user) {
    checkArgument(
        (user instanceof IdentifiedUser) || (user instanceof InternalUser),
        "user must be IdentifiedUser or InternalUser: %s",
        user);
  }

  private static Account.Id accountId(CurrentUser u) {
    checkUserType(u);
    return (u instanceof IdentifiedUser) ? u.getAccountId() : null;
  }

  private static PersonIdent ident(
      ChangeNoteUtil noteUtil,
      PersonIdent serverIdent,
      String anonymousCowardName,
      CurrentUser u,
      Date when) {
    checkUserType(u);
    if (u instanceof IdentifiedUser) {
      return noteUtil.newIdent(
          u.asIdentifiedUser().getAccount(), when, serverIdent, anonymousCowardName);
    } else if (u instanceof InternalUser) {
      return serverIdent;
    }
    throw new IllegalStateException();
  }

  public Change.Id getId() {
    return change.getId();
  }

  /**
   * @return notes for the state of this change prior to this update. If this update is part of a
   *     series managed by a {@link NoteDbUpdateManager}, then this reflects the state prior to the
   *     first update in the series. A null return value can only happen when the change is being
   *     rebuilt from NoteDb. A change that is in the process of being created will result in a
   *     non-null return value from this method, but a null return value from {@link
   *     ChangeNotes#getRevision()}.
   */
  @Nullable
  public ChangeNotes getNotes() {
    return notes;
  }

  public Change getChange() {
    return change;
  }

  public Date getWhen() {
    return when;
  }

  public PatchSet.Id getPatchSetId() {
    return psId;
  }

  public void setPatchSetId(PatchSet.Id psId) {
    checkArgument(psId == null || psId.getParentKey().equals(getId()));
    this.psId = psId;
  }

  public Account.Id getAccountId() {
    checkState(
        accountId != null,
        "author identity for %s is not from an IdentifiedUser: %s",
        getClass().getSimpleName(),
        authorIdent.toExternalString());
    return accountId;
  }

  public Account.Id getNullableAccountId() {
    return accountId;
  }

  protected PersonIdent newIdent(Account author, Date when) {
    return noteUtil.newIdent(author, when, serverIdent, anonymousCowardName);
  }

  /** Whether no updates have been done. */
  public abstract boolean isEmpty();

  /** Wether this update can only be a root commit. */
  public boolean isRootOnly() {
    return rootOnly;
  }

  /**
   * @return the NameKey for the project where the update will be stored, which is not necessarily
   *     the same as the change's project.
   */
  protected abstract Project.NameKey getProjectName();

  protected abstract String getRefName();

  /**
   * Apply this update to the given inserter.
   *
   * @param rw walk for reading back any objects needed for the update.
   * @param ins inserter to write to; callers should not flush.
   * @param curr the current tip of the branch prior to this update.
   * @return commit ID produced by inserting this update's commit, or null if this update is a no-op
   *     and should be skipped. The zero ID is a valid return value, and indicates the ref should be
   *     deleted.
   * @throws OrmException if a Gerrit-level error occurred.
   * @throws IOException if a lower-level error occurred.
   */
  final ObjectId apply(RevWalk rw, ObjectInserter ins, ObjectId curr)
      throws OrmException, IOException {
    if (isEmpty()) {
      return null;
    }

    // Allow this method to proceed even if migration.failChangeWrites() = true.
    // This may be used by an auto-rebuilding step that the caller does not plan
    // to actually store.

    checkArgument(rw.getObjectReader().getCreatedFromInserter() == ins);
    checkNotReadOnly();
    ObjectId z = ObjectId.zeroId();
    CommitBuilder cb = applyImpl(rw, ins, curr);
    if (cb == null) {
      result = z;
      return z; // Impl intends to delete the ref.
    } else if (cb == NO_OP_UPDATE) {
      return null; // Impl is a no-op.
    }
    cb.setAuthor(authorIdent);
    cb.setCommitter(new PersonIdent(serverIdent, when));
    if (!curr.equals(z)) {
      cb.setParentId(curr);
    } else {
      cb.setParentIds(); // Ref is currently nonexistent, commit has no parents.
    }
    if (cb.getTreeId() == null) {
      if (curr.equals(z)) {
        cb.setTreeId(emptyTree(ins)); // No parent, assume empty tree.
      } else {
        RevCommit p = rw.parseCommit(curr);
        cb.setTreeId(p.getTree()); // Copy tree from parent.
      }
    }
    result = ins.insert(cb);
    return result;
  }

  protected void checkNotReadOnly() throws OrmException {
    ChangeNotes notes = getNotes();
    if (notes == null) {
      // Can only happen during ChangeRebuilder, which will never include a read-only lease.
      return;
    }
    Timestamp until = notes.getReadOnlyUntil();
    if (until != null && NoteDbChangeState.timeForReadOnlyCheck(readOnlySkewMs).before(until)) {
      throw new OrmException("change " + notes.getChangeId() + " is read-only until " + until);
    }
  }

  /**
   * Create a commit containing the contents of this update.
   *
   * @param ins inserter to write to; callers should not flush.
   * @return a new commit builder representing this commit, or null to indicate the meta ref should
   *     be deleted as a result of this update. The parent, author, and committer fields in the
   *     return value are always overwritten. The tree ID may be unset by this method, which
   *     indicates to the caller that it should be copied from the parent commit. To indicate that
   *     this update is a no-op (but this could not be determined by {@link #isEmpty()}), return the
   *     sentinel {@link #NO_OP_UPDATE}.
   * @throws OrmException if a Gerrit-level error occurred.
   * @throws IOException if a lower-level error occurred.
   */
  protected abstract CommitBuilder applyImpl(RevWalk rw, ObjectInserter ins, ObjectId curr)
      throws OrmException, IOException;

  protected static final CommitBuilder NO_OP_UPDATE = new CommitBuilder();

  ObjectId getResult() {
    return result;
  }

  public boolean allowWriteToNewRef() {
    return true;
  }

  private static ObjectId emptyTree(ObjectInserter ins) throws IOException {
    return ins.insert(Constants.OBJ_TREE, new byte[] {});
  }

  protected void verifyComment(Comment c) {
    checkArgument(c.revId != null, "RevId required for comment: %s", c);
    checkArgument(
        c.author.getId().equals(getAccountId()),
        "The author for the following comment does not match the author of this %s (%s): %s",
        getClass().getSimpleName(),
        getAccountId(),
        c);
    checkArgument(
        c.getRealAuthor().getId().equals(realAccountId),
        "The real author for the following comment does not match the real"
            + " author of this %s (%s): %s",
        getClass().getSimpleName(),
        realAccountId,
        c);
  }
}
