// Copyright (C) 2016 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.entities;

import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.gerrit.common.Nullable;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Comparator;
import java.util.Objects;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.ObjectId;

/**
 * This class is a base class that can be extended by the different types of inline comment
 * entities.
 *
 * <p>Changing fields in this class changes the storage format of inline comments in NoteDb and may
 * require a corresponding data migration (adding new optional fields is generally okay).
 *
 * <p>Consider updating {@link #getCommentFieldApproximateSize()} when adding/changing fields.
 */
public abstract class Comment {
  public enum Status {
    DRAFT('d'),

    PUBLISHED('P');

    private final char code;

    Status(char c) {
      code = c;
    }

    public char getCode() {
      return code;
    }

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

  public static final class Key {
    public String uuid;
    public String filename;
    public int patchSetId;

    public Key(Key k) {
      this(k.uuid, k.filename, k.patchSetId);
    }

    public Key(String uuid, String filename, int patchSetId) {
      this.uuid = uuid;
      this.filename = filename;
      this.patchSetId = patchSetId;
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("uuid", uuid)
          .add("filename", filename)
          .add("patchSetId", patchSetId)
          .toString();
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Key) {
        Key k = (Key) o;
        return Objects.equals(uuid, k.uuid)
            && Objects.equals(filename, k.filename)
            && patchSetId == k.patchSetId;
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hash(uuid, filename, patchSetId);
    }
  }

  public static final class Identity {
    int id;

    public Identity(Account.Id id) {
      this.id = id.get();
    }

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

    @Override
    public boolean equals(Object o) {
      if (o instanceof Identity) {
        return id == ((Identity) o).id;
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hash(id);
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this).add("id", id).toString();
    }
  }

  /**
   * The Range class defines continuous range of character.
   *
   * <p>The pair (startLine, startChar) defines the first character in the range. The pair (endLine,
   * endChar) defines the first character AFTER the range (i.e. it doesn't belong the range).
   * (endLine, endChar) must be a valid character inside text, except EOF case.
   *
   * <p>Special cases:
   *
   * <ul>
   *   <li>Zero length range: (startLine, startChar) = (endLine, endChar). Range defines insert
   *       position right before the (startLine, startChar) character (for {@link FixReplacement})
   *   <li>EOF case - range includes the last character in the file:
   *       <ul>
   *         <li>if a file ends with EOL mark, then (endLine, endChar) = (num_of_lines + 1, 0)
   *         <li>if a file doesn't end with EOL mark, then (endLine, endChar) = (num_of_lines,
   *             num_of_chars_in_last_line)
   *       </ul>
   * </ul>
   */
  public static final class Range implements Comparable<Range> {
    private static final Comparator<Range> RANGE_COMPARATOR =
        Comparator.<Range>comparingInt(range -> range.startLine)
            .thenComparingInt(range -> range.startChar)
            .thenComparingInt(range -> range.endLine)
            .thenComparingInt(range -> range.endChar);

    public int startLine; // 1-based
    public int startChar; // 0-based
    public int endLine; // 1-based
    public int endChar; // 0-based

    public Range(Range r) {
      this(r.startLine, r.startChar, r.endLine, r.endChar);
    }

    public Range(com.google.gerrit.extensions.client.Comment.Range r) {
      this(r.startLine, r.startCharacter, r.endLine, r.endCharacter);
    }

    public Range(int startLine, int startChar, int endLine, int endChar) {
      this.startLine = startLine;
      this.startChar = startChar;
      this.endLine = endLine;
      this.endChar = endChar;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Range) {
        Range r = (Range) o;
        return startLine == r.startLine
            && startChar == r.startChar
            && endLine == r.endLine
            && endChar == r.endChar;
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hash(startLine, startChar, endLine, endChar);
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("startLine", startLine)
          .add("startChar", startChar)
          .add("endLine", endLine)
          .add("endChar", endChar)
          .toString();
    }

    @Override
    public int compareTo(Range otherRange) {
      return RANGE_COMPARATOR.compare(this, otherRange);
    }
  }

  public Key key;
  /** The line number (1-based) to which the comment refers, or 0 for a file comment. */
  public int lineNbr;

  public Identity author;
  protected Identity realAuthor;

  // TODO(issue-15525): Migrate this field from Timestamp to Instant
  public Timestamp writtenOn;

  public short side;
  public String message;
  public String parentUuid;
  public Range range;
  public String tag;

  /**
   * Hex commit SHA1 of the commit of the patchset to which this comment applies. Other classes call
   * this "commitId", but this class uses the old ReviewDb term "revId", and this field name is
   * serialized into JSON in NoteDb, so it can't easily be changed. Callers do not access this field
   * directly, and instead use the public getter/setter that wraps an ObjectId.
   */
  private String revId;

  public String serverId;

  public Comment(Comment c) {
    this(new Key(c.key), c.author.getId(), c.writtenOn.toInstant(), c.side, c.message, c.serverId);
    this.lineNbr = c.lineNbr;
    this.realAuthor = c.realAuthor;
    this.parentUuid = c.parentUuid;
    this.range = c.range != null ? new Range(c.range) : null;
    this.tag = c.tag;
    this.revId = c.revId;
  }

  public Comment(
      Key key, Account.Id author, Instant writtenOn, short side, String message, String serverId) {
    this.key = key;
    this.author = new Comment.Identity(author);
    this.realAuthor = this.author;
    this.writtenOn = Timestamp.from(writtenOn);
    this.side = side;
    this.message = message;
    this.serverId = serverId;
  }

  public void setWrittenOn(Instant writtenOn) {
    this.writtenOn = Timestamp.from(writtenOn);
  }

  public void setLineNbrAndRange(
      Integer lineNbr, com.google.gerrit.extensions.client.Comment.Range range) {
    this.lineNbr = range != null ? range.endLine : lineNbr != null ? lineNbr : 0;
    if (range != null) {
      this.range = new Comment.Range(range);
    }
  }

  public void setRange(CommentRange range) {
    this.range = range != null ? range.asCommentRange() : null;
  }

  @Nullable
  public ObjectId getCommitId() {
    return revId != null ? ObjectId.fromString(revId) : null;
  }

  public void setCommitId(@Nullable AnyObjectId commitId) {
    this.revId = commitId != null ? commitId.name() : null;
  }

  public void setRealAuthor(Account.Id id) {
    realAuthor = id != null && id.get() != author.id ? new Comment.Identity(id) : null;
  }

  public Identity getRealAuthor() {
    return realAuthor != null ? realAuthor : author;
  }

  /**
   * Returns the comment's approximate size. This is used to enforce size limits and should
   * therefore include all unbounded fields (e.g. String-s).
   */
  protected int getCommentFieldApproximateSize() {
    return nullableLength(message, parentUuid, tag, revId, serverId)
        + (key != null ? nullableLength(key.filename, key.uuid) : 0);
  }

  public abstract int getApproximateSize();

  static int nullableLength(String... strings) {
    int length = 0;
    for (String s : strings) {
      length += s == null ? 0 : s.length();
    }
    return length;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof Comment)) {
      return false;
    }
    Comment c = (Comment) o;
    return Objects.equals(key, c.key)
        && lineNbr == c.lineNbr
        && Objects.equals(author, c.author)
        && Objects.equals(realAuthor, c.realAuthor)
        && Objects.equals(writtenOn, c.writtenOn)
        && side == c.side
        && Objects.equals(message, c.message)
        && Objects.equals(parentUuid, c.parentUuid)
        && Objects.equals(range, c.range)
        && Objects.equals(tag, c.tag)
        && Objects.equals(revId, c.revId)
        && Objects.equals(serverId, c.serverId);
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        key,
        lineNbr,
        author,
        realAuthor,
        writtenOn,
        side,
        message,
        parentUuid,
        range,
        tag,
        revId,
        serverId);
  }

  @Override
  public String toString() {
    return toStringHelper().toString();
  }

  protected ToStringHelper toStringHelper() {
    return MoreObjects.toStringHelper(this)
        .add("key", key)
        .add("lineNbr", lineNbr)
        .add("author", author.getId())
        .add("realAuthor", realAuthor != null ? realAuthor.getId() : "")
        .add("writtenOn", writtenOn)
        .add("side", side)
        .add("message", Objects.toString(message, ""))
        .add("parentUuid", Objects.toString(parentUuid, ""))
        .add("range", Objects.toString(range, ""))
        .add("revId", Objects.toString(revId, ""))
        .add("tag", Objects.toString(tag, ""));
  }
}
