// 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.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import java.sql.Timestamp;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

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

  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  /** Template to identify an account in {@link ChangeMessage#message}. */
  public static final String ACCOUNT_TEMPLATE = "<GERRIT_ACCOUNT_%d>";

  public static final Pattern ACCOUNT_TEMPLATE_PATTERN =
      Pattern.compile("<GERRIT_ACCOUNT_([0-9]+)>");

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

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

    public abstract String uuid();
  }

  protected Key key;

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

  /** When this comment was drafted. */
  protected Timestamp 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 protected String message;

  /** {@link Account.Id}s that are used in {@link #message} template. */
  protected ImmutableSet<Account.Id> accountsInMessage;

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

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

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

  protected ChangeMessage() {}

  public static ChangeMessage create(
      final ChangeMessage.Key k, @Nullable Account.Id a, Timestamp 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,
      Timestamp 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;
    message.accountsInMessage =
        messageTemplate == null ? ImmutableSet.of() : parseTemplates(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;
  }

  /* Returns account ids that are used in {@code messageTemplate}. */
  public static ImmutableSet<Account.Id> parseTemplates(String messageTemplate) {
    Matcher matcher = ACCOUNT_TEMPLATE_PATTERN.matcher(messageTemplate);
    Set<Account.Id> accountsInTemplate = new HashSet<>();
    while (matcher.find()) {
      String accountId = matcher.group(1);
      Optional<Account.Id> parsedAccountId = Account.Id.tryParse(accountId);
      if (parsedAccountId.isPresent()) {
        accountsInTemplate.add(parsedAccountId.get());
      } else {
        logger.atFine().log("Failed to parse accountId from template %s", matcher.group());
      }
    }
    return ImmutableSet.copyOf(accountsInTemplate);
  }

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

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

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

  public Timestamp getWrittenOn() {
    return writtenOn;
  }

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

  /** Account ids, used in {@link #message} template. */
  public ImmutableSet<Account.Id> getAccountsInMessage() {
    return accountsInMessage == null ? ImmutableSet.of() : accountsInMessage;
  }

  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(accountsInMessage, m.accountsInMessage)
        && 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, accountsInMessage, patchset, tag, realAuthor);
  }

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