// 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 java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/** A single revision of a {@link Change}. */
public final class PatchSet {
  /** Is the reference name a change reference? */
  public static boolean isChangeRef(String name) {
    return Id.fromRef(name) != null;
  }

  /**
   * Is the reference name a change reference?
   *
   * @deprecated use isChangeRef instead.
   */
  @Deprecated
  public static boolean isRef(String name) {
    return isChangeRef(name);
  }

  static String joinGroups(List<String> groups) {
    if (groups == null) {
      throw new IllegalArgumentException("groups may not be null");
    }
    StringBuilder sb = new StringBuilder();
    boolean first = true;
    for (String g : groups) {
      if (!first) {
        sb.append(',');
      } else {
        first = false;
      }
      sb.append(g);
    }
    return sb.toString();
  }

  public static List<String> splitGroups(String joinedGroups) {
    if (joinedGroups == null) {
      throw new IllegalArgumentException("groups may not be null");
    }
    List<String> groups = new ArrayList<>();
    int i = 0;
    while (true) {
      int idx = joinedGroups.indexOf(',', i);
      if (idx < 0) {
        groups.add(joinedGroups.substring(i, joinedGroups.length()));
        break;
      }
      groups.add(joinedGroups.substring(i, idx));
      i = idx + 1;
    }
    return groups;
  }

  public static class Id extends IntKey<Change.Id> {
    private static final long serialVersionUID = 1L;

    @Column(id = 1)
    public Change.Id changeId;

    @Column(id = 2)
    public int patchSetId;

    public Id() {
      changeId = new Change.Id();
    }

    public Id(Change.Id change, int id) {
      this.changeId = change;
      this.patchSetId = id;
    }

    @Override
    public Change.Id getParentKey() {
      return changeId;
    }

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

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

    public String toRefName() {
      return changeId.refPrefixBuilder().append(patchSetId).toString();
    }

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

    /** Parse a PatchSet.Id from a {@link PatchSet#getRefName()} result. */
    public static Id fromRef(String ref) {
      int cs = Change.Id.startIndex(ref);
      if (cs < 0) {
        return null;
      }
      int ce = Change.Id.nextNonDigit(ref, cs);
      int patchSetId = fromRef(ref, ce);
      if (patchSetId < 0) {
        return null;
      }
      int changeId = Integer.parseInt(ref.substring(cs, ce));
      return new PatchSet.Id(new Change.Id(changeId), patchSetId);
    }

    static int fromRef(String ref, int changeIdEnd) {
      // Patch set ID.
      int ps = changeIdEnd + 1;
      if (ps >= ref.length() || ref.charAt(ps) == '0') {
        return -1;
      }
      for (int i = ps; i < ref.length(); i++) {
        if (ref.charAt(i) < '0' || ref.charAt(i) > '9') {
          return -1;
        }
      }
      return Integer.parseInt(ref.substring(ps));
    }

    public String getId() {
      return toId(patchSetId);
    }

    public static String toId(int number) {
      return number == 0 ? "edit" : String.valueOf(number);
    }
  }

  @Column(id = 1, name = Column.NONE)
  protected Id id;

  @Column(id = 2, notNull = false)
  protected RevId revision;

  @Column(id = 3, name = "uploader_account_id")
  protected Account.Id uploader;

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

  // @Column(id = 5)

  /**
   * Opaque group identifier, usually assigned during creation.
   *
   * <p>This field is actually a comma-separated list of values, as in rare cases involving merge
   * commits a patch set may belong to multiple groups.
   *
   * <p>Changes on the same branch having patch sets with intersecting groups are considered
   * related, as in the "Related Changes" tab.
   */
  @Column(id = 6, notNull = false, length = Integer.MAX_VALUE)
  protected String groups;

  // DELETED id = 7 (pushCertficate)

  /** Certificate sent with a push that created this patch set. */
  @Column(id = 8, notNull = false, length = Integer.MAX_VALUE)
  protected String pushCertificate;

  /**
   * Optional user-supplied description for this patch set.
   *
   * <p>When this field is null, the description was never set on the patch set. When this field is
   * an empty string, the description was set and later cleared.
   */
  @Column(id = 9, notNull = false, length = Integer.MAX_VALUE)
  protected String description;

  protected PatchSet() {}

  public PatchSet(PatchSet.Id k) {
    id = k;
  }

  public PatchSet(PatchSet src) {
    this.id = src.id;
    this.revision = src.revision;
    this.uploader = src.uploader;
    this.createdOn = src.createdOn;
    this.groups = src.groups;
    this.pushCertificate = src.pushCertificate;
    this.description = src.description;
  }

  public PatchSet.Id getId() {
    return id;
  }

  public int getPatchSetId() {
    return id.get();
  }

  public RevId getRevision() {
    return revision;
  }

  public void setRevision(RevId i) {
    revision = i;
  }

  public Account.Id getUploader() {
    return uploader;
  }

  public void setUploader(Account.Id who) {
    uploader = who;
  }

  public Timestamp getCreatedOn() {
    return createdOn;
  }

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

  public List<String> getGroups() {
    if (groups == null) {
      return Collections.emptyList();
    }
    return splitGroups(groups);
  }

  public void setGroups(List<String> groups) {
    if (groups == null) {
      groups = Collections.emptyList();
    }
    this.groups = joinGroups(groups);
  }

  public String getRefName() {
    return id.toRefName();
  }

  public String getPushCertificate() {
    return pushCertificate;
  }

  public void setPushCertificate(String cert) {
    pushCertificate = cert;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

  @Override
  public String toString() {
    return "[PatchSet " + getId().toString() + "]";
  }
}
