// 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.extensions.client.ChangeStatus;
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;
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;

    @Column(id = 1)
    public 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;
    }

    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(final 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. */
  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#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;

  /** 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 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, ChangeStatus.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, 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(final char c) {
      for (final Status s : Status.values()) {
        if (s.code == c) {
          return s;
        }
      }
      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 */
  @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;

  // DELETED: id = 6 (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;

  // DELETED: id = 9 (open)

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

  // DELETED: id = 11 (nbrPatchSets)

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

  // 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.
   */
  @Column(id = 17, notNull = false)
  protected String originalSubject;

  /**
   * Unique id for the changes submitted together assigned during merging. Only set if the status is
   * MERGED.
   */
  @Column(id = 18, notNull = false)
  protected String submissionId;

  /** Allows assigning a change to a user. */
  @Column(id = 19, notNull = false)
  protected Account.Id assignee;

  /** @see com.google.gerrit.server.notedb.NoteDbChangeState */
  @Column(id = 101, notNull = false, length = Integer.MAX_VALUE)
  protected String noteDbState;

  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;
    noteDbState = other.noteDbState;
  }

  /** 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 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(final 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 String getTopic() {
    return topic;
  }

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

  public String getNoteDbState() {
    return noteDbState;
  }

  public void setNoteDbState(String state) {
    noteDbState = state;
  }

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