// 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.entities;

import com.google.auto.value.AutoValue;
import com.google.gerrit.common.ConvertibleToProto;
import com.google.gerrit.common.Nullable;
import java.time.Instant;
import java.util.Objects;

/**
 * A message attached to a {@link Change}. This message is persisted in data storage, that is why it
 * must have template form that does not contain Gerrit user identifiable information. Hence, it
 * requires processing to convert it to user-facing form.
 *
 * <p>These messages are normally auto-generated by gerrit operations, but might also incorporate
 * user input.
 */
public final class ChangeMessage {

  public static Key key(Change.Id changeId, String uuid) {
    return new AutoValue_ChangeMessage_Key(changeId, uuid);
  }

  @AutoValue
  @ConvertibleToProto
  public abstract static class Key {
    public abstract Change.Id changeId();

    public abstract String uuid();
  }

  private Key key;

  /** Who wrote this comment; null if it was written by the Gerrit system. */
  @Nullable private Account.Id author;

  /** When this comment was drafted. */
  private Instant writtenOn;

  /**
   * The text left by the user or Gerrit system in template form, that is free of Gerrit User
   * Identifiable Information and can be persisted in data storage.
   */
  @Nullable private String message;

  /** Which patchset (if any) was this message generated from? */
  @Nullable private PatchSet.Id patchset;

  /** Tag associated with change message */
  @Nullable private String tag;

  /** Real user that added this message on behalf of the user recorded in {@link #author}. */
  @Nullable private Account.Id realAuthor;

  private ChangeMessage() {}

  public static ChangeMessage create(
      final ChangeMessage.Key k, @Nullable Account.Id a, Instant wo, @Nullable PatchSet.Id psid) {
    return create(k, a, wo, psid, /*messageTemplate=*/ null, /*realAuthor=*/ null, /*tag=*/ null);
  }

  public static ChangeMessage create(
      final ChangeMessage.Key k,
      @Nullable Account.Id a,
      Instant wo,
      @Nullable PatchSet.Id psid,
      @Nullable String messageTemplate,
      @Nullable Account.Id realAuthor,
      @Nullable String tag) {
    ChangeMessage message = new ChangeMessage();
    message.key = k;
    message.author = a;
    message.writtenOn = wo;
    message.patchset = psid;
    message.message = messageTemplate;
    // Use null for same real author, as before the column was added.
    message.realAuthor = Objects.equals(a, realAuthor) ? null : realAuthor;
    message.tag = tag;
    return message;
  }

  public ChangeMessage.Key getKey() {
    return key;
  }

  /** If null, the message was written 'by the Gerrit system'. */
  @Nullable
  public Account.Id getAuthor() {
    return author;
  }

  public Account.Id getRealAuthor() {
    return realAuthor != null ? realAuthor : getAuthor();
  }

  public Instant getWrittenOn() {
    return writtenOn;
  }

  /** Message template, as persisted in data storage. */
  public String getMessage() {
    return message;
  }

  public String getTag() {
    return tag;
  }

  public PatchSet.Id getPatchSetId() {
    return patchset;
  }

  @Override
  public boolean equals(Object o) {
    if (!(o instanceof ChangeMessage)) {
      return false;
    }
    ChangeMessage m = (ChangeMessage) o;
    return Objects.equals(key, m.key)
        && Objects.equals(author, m.author)
        && Objects.equals(writtenOn, m.writtenOn)
        && Objects.equals(message, m.message)
        && Objects.equals(patchset, m.patchset)
        && Objects.equals(tag, m.tag)
        && Objects.equals(realAuthor, m.realAuthor);
  }

  @Override
  public int hashCode() {
    return Objects.hash(key, author, writtenOn, message, patchset, tag, realAuthor);
  }

  @Override
  public String toString() {
    return "ChangeMessage{"
        + "key="
        + key
        + ", author="
        + author
        + ", realAuthor="
        + realAuthor
        + ", writtenOn="
        + writtenOn
        + ", patchset="
        + patchset
        + ", tag="
        + tag
        + ", message=["
        + message
        + "]}";
  }
}
