// Copyright (C) 2008 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.reviewdb.client;

import com.google.gwtorm.client.Column;
import com.google.gwtorm.client.IntKey;
import com.google.gwtorm.client.RowVersion;
import com.google.gwtorm.client.StringKey;

import java.sql.Timestamp;

/**
 * A change proposed to be merged into a {@link Branch}.
 * <p>
 * The data graph rooted below a Change can be quite complex:
 *
 * <pre>
 *   {@link Change}
 *     |
 *     +- {@link ChangeMessage}: &quot;cover letter&quot; or general comment.
 *     |
 *     +- {@link PatchSet}: a single variant of this change.
 *          |
 *          +- {@link PatchSetApproval}: a +/- vote on the change's current state.
 *          |
 *          +- {@link PatchSetAncestor}: parents of this change's commit.
 *          |
 *          +- {@link PatchLineComment}: comment about a specific line
 * </pre>
 * <p>
 * <h5>PatchSets</h5>
 * <p>
 * Every change has at least one PatchSet. A change starts out with one
 * PatchSet, the initial proposal put forth by the change owner. This
 * {@link Account} is usually also listed as the author and committer in the
 * PatchSetInfo.
 * <p>
 * The {@link PatchSetAncestor} entities are a mirror of the Git commit
 * metadata, providing access to the information without needing direct
 * accessing Git. These entities are actually legacy artifacts from Gerrit 1.x
 * and could be removed, replaced by direct RevCommit access.
 * <p>
 * Each PatchSet contains zero or more Patch records, detailing the file paths
 * impacted by the change (otherwise known as, the file paths the author
 * added/deleted/modified). Sometimes a merge commit can contain zero patches,
 * if the merge has no conflicts, or has no impact other than to cut off a line
 * of development.
 * <p>
 * Each PatchLineComment is a draft or a published comment about a single line
 * of the associated file. These are the inline comment entities created by
 * users as they perform a review.
 * <p>
 * When additional PatchSets appear under a change, these PatchSets reference
 * <i>replacement</i> commits; alternative commits that could be made to the
 * project instead of the original commit referenced by the first PatchSet.
 * <p>
 * A change has at most one current PatchSet. The current PatchSet is updated
 * when a new replacement PatchSet is uploaded. When a change is submitted, the
 * current patch set is what is merged into the destination branch.
 * <p>
 * <h5>ChangeMessage</h5>
 * <p>
 * The ChangeMessage entity is a general free-form comment about the whole
 * change, rather than PatchLineComment's file and line specific context. The
 * ChangeMessage appears at the start of any email generated by Gerrit, and is
 * shown on the change overview page, rather than in a file-specific context.
 * Users often use this entity to describe general remarks about the overall
 * concept proposed by the change.
 * <p>
 * <h5>PatchSetApproval</h5>
 * <p>
 * PatchSetApproval entities exist to fill in the <i>cells</i> of the approvals
 * table in the web UI. That is, a single PatchSetApproval record's key is the
 * tuple {@code (PatchSet,Account,ApprovalCategory)}. Each PatchSetApproval
 * carries with it a small score value, typically within the range -2..+2.
 * <p>
 * If an Account has created only PatchSetApprovals with a score value of 0, the
 * Change shows in their dashboard, and they are said to be CC'd (carbon copied)
 * on the Change, but are not a direct reviewer. This often happens when an
 * account was specified at upload time with the {@code --cc} command line flag,
 * or have published comments, but left the approval scores at 0 ("No Score").
 * <p>
 * If an Account has one or more PatchSetApprovals with a score != 0, the Change
 * shows in their dashboard, and they are said to be an active reviewer. Such
 * individuals are highlighted when notice of a replacement patch set is sent,
 * or when notice of the change submission occurs.
 */
public final class Change {
  public static class Id extends IntKey<com.google.gwtorm.client.Key<?>> {
    private static final long serialVersionUID = 1L;

    @Column(id = 1)
    protected int id;

    protected Id() {
    }

    public Id(final int id) {
      this.id = id;
    }

    @Override
    public int get() {
      return id;
    }

    @Override
    protected void set(int newValue) {
      id = newValue;
    }

    /** Parse a Change.Id out of a string representation. */
    public static Id parse(final String str) {
      final Id r = new Id();
      r.fromString(str);
      return r;
    }

    public static Id fromRef(final String ref) {
      return PatchSet.Id.fromRef(ref).getParentKey();
    }
  }

  /** Globally unique identification of this change. */
  public static class Key extends StringKey<com.google.gwtorm.client.Key<?>> {
    private static final long serialVersionUID = 1L;

    @Column(id = 1, length = 60)
    protected String id;

    protected Key() {
    }

    public Key(final String id) {
      this.id = id;
    }

    @Override
    public String get() {
      return id;
    }

    @Override
    protected void set(String newValue) {
      id = newValue;
    }

    /** Construct a key that is after all keys prefixed by this key. */
    public Key max() {
      final StringBuilder revEnd = new StringBuilder(get().length() + 1);
      revEnd.append(get());
      revEnd.append('\u9fa5');
      return new Key(revEnd.toString());
    }

    /** Obtain a shorter version of this key string, using a leading prefix. */
    public String abbreviate() {
      final String s = get();
      return s.substring(0, Math.min(s.length(), 9));
    }

    /** Parse a Change.Key out of a string representation. */
    public static Key parse(final String str) {
      final Key r = new Key();
      r.fromString(str);
      return r;
    }
  }

  /** Minimum database status constant for an open change. */
  private static final char MIN_OPEN = 'a';
  /** Database constant for {@link Status#NEW}. */
  public static final char STATUS_NEW = 'n';
  /** Database constant for {@link Status#SUBMITTED}. */
  public static final char STATUS_SUBMITTED = 's';
  /** Database constant for {@link Status#DRAFT}. */
  public static final char STATUS_DRAFT = 'd';
  /** Maximum database status constant for an open change. */
  private static final char MAX_OPEN = 'z';

  /** Database constant for {@link Status#MERGED}. */
  public static final char STATUS_MERGED = 'M';

  /** ID number of the first patch set in a change. */
  public static final int INITIAL_PATCH_SET_ID = 1;

  /**
   * Current state within the basic workflow of the change.
   *
   * <p>
   * Within the database, lower case codes ('a'..'z') indicate a change that is
   * still open, and that can be modified/refined further, while upper case
   * codes ('A'..'Z') indicate a change that is closed and cannot be further
   * modified.
   * */
  public static enum Status {
    /**
     * Change is open and pending review, or review is in progress.
     *
     * <p>
     * This is the default state assigned to a change when it is first created
     * in the database. A change stays in the NEW state throughout its review
     * cycle, until the change is submitted or abandoned.
     *
     * <p>
     * Changes in the NEW state can be moved to:
     * <ul>
     * <li>{@link #SUBMITTED} - when the Submit Patch Set action is used;
     * <li>{@link #ABANDONED} - when the Abandon action is used.
     * </ul>
     */
    NEW(STATUS_NEW),

    /**
     * Change is open, but has been submitted to the merge queue.
     *
     * <p>
     * A change enters the SUBMITTED state when an authorized user presses the
     * "submit" action through the web UI, requesting that Gerrit merge the
     * change's current patch set into the destination branch.
     *
     * <p>
     * Typically a change resides in the SUBMITTED for only a brief sub-second
     * period while the merge queue fires and the destination branch is updated.
     * However, if a dependency commit (a {@link PatchSetAncestor}, directly or
     * transitively) is not yet merged into the branch, the change will hang in
     * the SUBMITTED state indefinitely.
     *
     * <p>
     * Changes in the SUBMITTED state can be moved to:
     * <ul>
     * <li>{@link #NEW} - when a replacement patch set is supplied, OR when a
     * merge conflict is detected;
     * <li>{@link #MERGED} - when the change has been successfully merged into
     * the destination branch;
     * <li>{@link #ABANDONED} - when the Abandon action is used.
     * </ul>
     */
    SUBMITTED(STATUS_SUBMITTED),

    /**
     * Change is a draft change that only consists of draft patchsets.
     *
     * <p>
     * This is a change that is not meant to be submitted or reviewed yet. If
     * the uploader publishes the change, it becomes a NEW change.
     * Publishing is a one-way action, a change cannot return to DRAFT status.
     * Draft changes are only visible to the uploader and those explicitly
     * added as reviewers.
     *
     * <p>
     * Changes in the DRAFT state can be moved to:
     * <ul>
     * <li>{@link #NEW} - when the change is published, it becomes a new change;
     * </ul>
     */
    DRAFT(STATUS_DRAFT),

    /**
     * Change is closed, and submitted to its destination branch.
     *
     * <p>
     * Once a change has been merged, it cannot be further modified by adding a
     * replacement patch set. Draft comments however may be published,
     * supporting a post-submit review.
     */
    MERGED(STATUS_MERGED),

    /**
     * Change is closed, but was not submitted to its destination branch.
     *
     * <p>
     * Once a change has been abandoned, it cannot be further modified by adding
     * a replacement patch set, and it cannot be merged. Draft comments however
     * may be published, permitting reviewers to send constructive feedback.
     */
    ABANDONED('A');

    private final char code;
    private final boolean closed;

    private Status(final char c) {
      code = c;
      closed = !(MIN_OPEN <= c && c <= MAX_OPEN);
    }

    public char getCode() {
      return code;
    }

    public boolean isOpen() {
      return !closed;
    }

    public boolean isClosed() {
      return closed;
    }

    public static Status forCode(final char c) {
      for (final Status s : Status.values()) {
        if (s.code == c) {
          return s;
        }
      }
      return null;
    }
  }

  /** Locally assigned unique identifier of the change */
  @Column(id = 1)
  protected Id changeId;

  /** Globally assigned unique identifier of the change */
  @Column(id = 2)
  protected Key changeKey;

  /** optimistic locking */
  @Column(id = 3)
  @RowVersion
  protected int rowVersion;

  /** When this change was first introduced into the database. */
  @Column(id = 4)
  protected Timestamp createdOn;

  /**
   * When was a meaningful modification last made to this record's data
   * <p>
   * Note, this update timestamp includes its children.
   */
  @Column(id = 5)
  protected Timestamp lastUpdatedOn;

  /** A {@link #lastUpdatedOn} ASC,{@link #changeId} ASC for sorting. */
  @Column(id = 6, length = 16)
  protected String sortKey;

  @Column(id = 7, name = "owner_account_id")
  protected Account.Id owner;

  /** The branch (and project) this change merges into. */
  @Column(id = 8)
  protected Branch.NameKey dest;

  /** Is the change currently open? Set to {@link #status}.isOpen(). */
  @Column(id = 9)
  protected boolean open;

  /** Current state code; see {@link Status}. */
  @Column(id = 10)
  protected char status;

  /** The current patch set. */
  @Column(id = 12)
  protected int currentPatchSetId;

  /** Subject from the current patch set. */
  @Column(id = 13)
  protected String subject;

  /** Topic name assigned by the user, if any. */
  @Column(id = 14, notNull = false)
  protected String topic;

  /**
   * Null if the change has never been tested.
   * Empty if it has been tested but against a branch that does
   * not exist.
   */
  @Column(id = 15, notNull = false)
  protected RevId lastSha1MergeTested;

  @Column(id = 16)
  protected boolean mergeable;

  protected Change() {
  }

  public Change(Change.Key newKey, Change.Id newId, Account.Id ownedBy,
      Branch.NameKey forBranch, Timestamp ts) {
    changeKey = newKey;
    changeId = newId;
    createdOn = ts;
    lastUpdatedOn = createdOn;
    owner = ownedBy;
    dest = forBranch;
    setStatus(Status.NEW);
    setLastSha1MergeTested(null);
  }

  /** Legacy 32 bit integer identity for a change. */
  public Change.Id getId() {
    return changeId;
  }

  /** Legacy 32 bit integer identity for a change. */
  public int getChangeId() {
    return changeId.get();
  }

  /** The Change-Id tag out of the initial commit, or a natural key. */
  public Change.Key getKey() {
    return changeKey;
  }

  public void setKey(final Change.Key k) {
    changeKey = k;
  }

  public Timestamp getCreatedOn() {
    return createdOn;
  }

  public Timestamp getLastUpdatedOn() {
    return lastUpdatedOn;
  }

  public void setLastUpdatedOn(Timestamp now) {
    lastUpdatedOn = now;
  }

  public int getRowVersion() {
    return rowVersion;
  }

  public String getSortKey() {
    return sortKey;
  }

  public void setSortKey(final String newSortKey) {
    sortKey = newSortKey;
  }

  public Account.Id getOwner() {
    return owner;
  }

  public Branch.NameKey getDest() {
    return dest;
  }

  public Project.NameKey getProject() {
    return dest.getParentKey();
  }

  public String getSubject() {
    return subject;
  }

  /** Get the id of the most current {@link PatchSet} in this change. */
  public PatchSet.Id currentPatchSetId() {
    if (currentPatchSetId > 0) {
      return new PatchSet.Id(changeId, currentPatchSetId);
    }
    return null;
  }

  public void setCurrentPatchSet(final PatchSetInfo ps) {
    currentPatchSetId = ps.getKey().get();
    subject = ps.getSubject();
  }

  public Status getStatus() {
    return Status.forCode(status);
  }

  public void setStatus(final Status newStatus) {
    open = newStatus.isOpen();
    status = newStatus.getCode();
  }

  public String getTopic() {
    return topic;
  }

  public void setTopic(String topic) {
    this.topic = topic;
  }

  public RevId getLastSha1MergeTested() {
    return lastSha1MergeTested;
  }

  public void setLastSha1MergeTested(RevId lastSha1MergeTested) {
    this.lastSha1MergeTested = lastSha1MergeTested;
  }

  public boolean isMergeable() {
    return mergeable;
  }

  public void setMergeable(boolean mergeable) {
    this.mergeable = mergeable;
  }
}
