// 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 static com.google.gerrit.reviewdb.client.RefNames.REFS_CHANGES;

import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gwtorm.client.IntKey;
import com.google.gwtorm.client.StringKey;
import java.sql.Timestamp;
import java.util.Arrays;

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

    public int id;

    protected Id() {}

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

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

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

    public String toRefPrefix() {
      return refPrefixBuilder().toString();
    }

    StringBuilder refPrefixBuilder() {
      StringBuilder r = new StringBuilder(32).append(REFS_CHANGES);
      int m = id % 100;
      if (m < 10) {
        r.append('0');
      }
      return r.append(m).append('/').append(id).append('/');
    }

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

    public static Id fromRef(String ref) {
      if (RefNames.isRefsEdit(ref)) {
        return fromEditRefPart(ref);
      }
      int cs = startIndex(ref);
      if (cs < 0) {
        return null;
      }
      int ce = nextNonDigit(ref, cs);
      if (ref.substring(ce).equals(RefNames.META_SUFFIX)
          || ref.substring(ce).equals(RefNames.ROBOT_COMMENTS_SUFFIX)
          || PatchSet.Id.fromRef(ref, ce) >= 0) {
        return new Change.Id(Integer.parseInt(ref.substring(cs, ce)));
      }
      return null;
    }

    public static Id fromAllUsersRef(String ref) {
      if (ref == null) {
        return null;
      }
      String prefix;
      if (ref.startsWith(RefNames.REFS_STARRED_CHANGES)) {
        prefix = RefNames.REFS_STARRED_CHANGES;
      } else if (ref.startsWith(RefNames.REFS_DRAFT_COMMENTS)) {
        prefix = RefNames.REFS_DRAFT_COMMENTS;
      } else {
        return null;
      }
      int cs = startIndex(ref, prefix);
      if (cs < 0) {
        return null;
      }
      int ce = nextNonDigit(ref, cs);
      if (ce < ref.length() && ref.charAt(ce) == '/' && isNumeric(ref, ce + 1)) {
        return new Change.Id(Integer.parseInt(ref.substring(cs, ce)));
      }
      return null;
    }

    private static boolean isNumeric(String s, int off) {
      if (off >= s.length()) {
        return false;
      }
      for (int i = off; i < s.length(); i++) {
        if (!Character.isDigit(s.charAt(i))) {
          return false;
        }
      }
      return true;
    }

    public static Id fromEditRefPart(String ref) {
      int startChangeId = ref.indexOf(RefNames.EDIT_PREFIX) + RefNames.EDIT_PREFIX.length();
      int endChangeId = nextNonDigit(ref, startChangeId);
      String id = ref.substring(startChangeId, endChangeId);
      if (id != null && !id.isEmpty()) {
        return new Change.Id(Integer.parseInt(id));
      }
      return null;
    }

    public static Id fromRefPart(String ref) {
      Integer id = RefNames.parseShardedRefPart(ref);
      return id != null ? new Change.Id(id) : null;
    }

    static int startIndex(String ref) {
      return startIndex(ref, REFS_CHANGES);
    }

    static int startIndex(String ref, String expectedPrefix) {
      if (ref == null || !ref.startsWith(expectedPrefix)) {
        return -1;
      }

      // Last 2 digits.
      int ls = expectedPrefix.length();
      int le = nextNonDigit(ref, ls);
      if (le - ls != 2 || le >= ref.length() || ref.charAt(le) != '/') {
        return -1;
      }

      // Change ID.
      int cs = le + 1;
      if (cs >= ref.length() || ref.charAt(cs) == '0') {
        return -1;
      }
      int ce = nextNonDigit(ref, cs);
      if (ce >= ref.length() || ref.charAt(ce) != '/') {
        return -1;
      }
      switch (ce - cs) {
        case 0:
          return -1;
        case 1:
          if (ref.charAt(ls) != '0' || ref.charAt(ls + 1) != ref.charAt(cs)) {
            return -1;
          }
          break;
        default:
          if (ref.charAt(ls) != ref.charAt(ce - 2) || ref.charAt(ls + 1) != ref.charAt(ce - 1)) {
            return -1;
          }
          break;
      }
      return cs;
    }

    static int nextNonDigit(String s, int i) {
      while (i < s.length() && s.charAt(i) >= '0' && s.charAt(i) <= '9') {
        i++;
      }
      return i;
    }
  }

  /**
   * Globally unique identification of this change. This generally takes the form of a string
   * "Ixxxxxx...", and is stored in the Change-Id footer of a commit.
   */
  public static class Key extends StringKey<com.google.gwtorm.client.Key<?>> {
    private static final long serialVersionUID = 1L;

    protected String id;

    protected Key() {}

    public Key(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(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';
  /** 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;

  /** Change-Id pattern. */
  public static final String CHANGE_ID_PATTERN = "^[iI][0-9a-f]{4,}.*$";

  /**
   * 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 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 #MERGED} - when the Submit Patch Set action is used;
     *   <li>{@link #ABANDONED} - when the Abandon action is used.
     * </ul>
     */
    NEW(STATUS_NEW, ChangeStatus.NEW),

    /**
     * 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
     */
    MERGED(STATUS_MERGED, ChangeStatus.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', ChangeStatus.ABANDONED);

    static {
      boolean ok = true;
      if (Status.values().length != ChangeStatus.values().length) {
        ok = false;
      }
      for (Status s : Status.values()) {
        ok &= s.name().equals(s.changeStatus.name());
      }
      if (!ok) {
        throw new IllegalStateException(
            "Mismatched status mapping: "
                + Arrays.asList(Status.values())
                + " != "
                + Arrays.asList(ChangeStatus.values()));
      }
    }

    private final char code;
    private final boolean closed;
    private final ChangeStatus changeStatus;

    Status(char c, ChangeStatus cs) {
      code = c;
      closed = !(MIN_OPEN <= c && c <= MAX_OPEN);
      changeStatus = cs;
    }

    public char getCode() {
      return code;
    }

    public boolean isOpen() {
      return !closed;
    }

    public boolean isClosed() {
      return closed;
    }

    public ChangeStatus asChangeStatus() {
      return changeStatus;
    }

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

      // TODO(davido): Remove in 3.0, after all sites upgraded to version,
      // where DRAFT status was removed. This code path is still needed,
      // when changes are deserialized from the secondary index, during
      // the online migration to the new schema version wasn't completed.
      if (c == 'd') {
        return Status.NEW;
      }
      return null;
    }

    public static Status forChangeStatus(ChangeStatus cs) {
      for (Status s : Status.values()) {
        if (s.changeStatus == cs) {
          return s;
        }
      }
      return null;
    }
  }

  /** Locally assigned unique identifier of the change */
  protected Id changeId;

  /** Globally assigned unique identifier of the change */
  protected Key changeKey;

  /** optimistic locking */
  protected int rowVersion;

  /** When this change was first introduced into the database. */
  protected Timestamp createdOn;

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

  // DELETED: id = 6 (sortkey)

  protected Account.Id owner;

  /** The branch (and project) this change merges into. */
  protected Branch.NameKey dest;

  // DELETED: id = 9 (open)

  /** Current state code; see {@link Status}. */
  protected char status;

  // DELETED: id = 11 (nbrPatchSets)

  /** The current patch set. */
  protected int currentPatchSetId;

  /** Subject from the current patch set. */
  protected String subject;

  /** Topic name assigned by the user, if any. */
  @Nullable protected String topic;

  // DELETED: id = 15 (lastSha1MergeTested)
  // DELETED: id = 16 (mergeable)

  /**
   * First line of first patch set's commit message.
   *
   * <p>Unlike {@link #subject}, this string does not change if future patch sets change the first
   * line.
   */
  @Nullable protected String originalSubject;

  /**
   * Unique id for the changes submitted together assigned during merging. Only set if the status is
   * MERGED.
   */
  @Nullable protected String submissionId;

  /** Allows assigning a change to a user. */
  @Nullable protected Account.Id assignee;

  /** Whether the change is private. */
  protected boolean isPrivate;

  /** Whether the change is work in progress. */
  protected boolean workInProgress;

  /** Whether the change has started review. */
  protected boolean reviewStarted;

  /** References a change that this change reverts. */
  @Nullable protected Id revertOf;

  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);
  }

  public Change(Change other) {
    assignee = other.assignee;
    changeId = other.changeId;
    changeKey = other.changeKey;
    rowVersion = other.rowVersion;
    createdOn = other.createdOn;
    lastUpdatedOn = other.lastUpdatedOn;
    owner = other.owner;
    dest = other.dest;
    status = other.status;
    currentPatchSetId = other.currentPatchSetId;
    subject = other.subject;
    originalSubject = other.originalSubject;
    submissionId = other.submissionId;
    topic = other.topic;
    isPrivate = other.isPrivate;
    workInProgress = other.workInProgress;
    reviewStarted = other.reviewStarted;
    revertOf = other.revertOf;
  }

  /** 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(Change.Key k) {
    changeKey = k;
  }

  public Account.Id getAssignee() {
    return assignee;
  }

  public void setAssignee(Account.Id a) {
    assignee = a;
  }

  public Timestamp getCreatedOn() {
    return createdOn;
  }

  public void setCreatedOn(Timestamp ts) {
    createdOn = ts;
  }

  public Timestamp getLastUpdatedOn() {
    return lastUpdatedOn;
  }

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

  public int getRowVersion() {
    return rowVersion;
  }

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

  public void setOwner(Account.Id owner) {
    this.owner = owner;
  }

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

  public void setDest(Branch.NameKey dest) {
    this.dest = dest;
  }

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

  public String getSubject() {
    return subject;
  }

  public String getOriginalSubject() {
    return originalSubject != null ? originalSubject : subject;
  }

  public String getOriginalSubjectOrNull() {
    return originalSubject;
  }

  /** 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(PatchSetInfo ps) {
    if (originalSubject == null && subject != null) {
      // Change was created before schema upgrade. Use the last subject
      // associated with this change, as the most recent discussion will
      // be under that thread in an email client such as GMail.
      originalSubject = subject;
    }

    currentPatchSetId = ps.getKey().get();
    subject = ps.getSubject();

    if (originalSubject == null) {
      // Newly created changes remember the first commit's subject.
      originalSubject = subject;
    }
  }

  public void setCurrentPatchSet(PatchSet.Id psId, String subject, String originalSubject) {
    if (!psId.getParentKey().equals(changeId)) {
      throw new IllegalArgumentException("patch set ID " + psId + " is not for change " + changeId);
    }
    currentPatchSetId = psId.get();
    this.subject = subject;
    this.originalSubject = originalSubject;
  }

  public void clearCurrentPatchSet() {
    currentPatchSetId = 0;
    subject = null;
    originalSubject = null;
  }

  public String getSubmissionId() {
    return submissionId;
  }

  public void setSubmissionId(String id) {
    this.submissionId = id;
  }

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

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

  public boolean isNew() {
    return getStatus().equals(Status.NEW);
  }

  public boolean isMerged() {
    return getStatus().equals(Status.MERGED);
  }

  public boolean isAbandoned() {
    return getStatus().equals(Status.ABANDONED);
  }

  public boolean isClosed() {
    return isAbandoned() || isMerged();
  }

  public String getTopic() {
    return topic;
  }

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

  public boolean isPrivate() {
    return isPrivate;
  }

  public void setPrivate(boolean isPrivate) {
    this.isPrivate = isPrivate;
  }

  public boolean isWorkInProgress() {
    return workInProgress;
  }

  public void setWorkInProgress(boolean workInProgress) {
    this.workInProgress = workInProgress;
  }

  public boolean hasReviewStarted() {
    return reviewStarted;
  }

  public void setReviewStarted(boolean reviewStarted) {
    this.reviewStarted = reviewStarted;
  }

  public void setRevertOf(Id revertOf) {
    this.revertOf = revertOf;
  }

  public Id getRevertOf() {
    return this.revertOf;
  }

  @Override
  public String toString() {
    return new StringBuilder(getClass().getSimpleName())
        .append('{')
        .append(changeId)
        .append(" (")
        .append(changeKey)
        .append("), ")
        .append("dest=")
        .append(dest)
        .append(", ")
        .append("status=")
        .append(status)
        .append('}')
        .toString();
  }
}
