// Copyright (C) 2020 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.server.mail.send;

import static com.google.common.base.Preconditions.checkState;

import com.google.auto.value.AutoValue;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.mail.MailMessage;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.update.RepoView;
import com.google.inject.Inject;
import java.io.IOException;
import java.time.Instant;
import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;

/** A generator class that creates a {@link MessageId} */
public class MessageIdGenerator {
  private final GitRepositoryManager repositoryManager;
  private final AllUsersName allUsersName;

  @Inject
  public MessageIdGenerator(GitRepositoryManager repositoryManager, AllUsersName allUsersName) {
    this.repositoryManager = repositoryManager;
    this.allUsersName = allUsersName;
  }

  /**
   * A unique id used which is a part of the header of all emails sent through by Gerrit. All of the
   * emails are sent via {@link OutgoingEmail#send()}.
   */
  @AutoValue
  public abstract static class MessageId {
    public abstract String id();
  }

  /**
   * Create a {@link MessageId} as a result of a change update.
   *
   * @param repoView
   * @param patchsetId
   * @return MessageId that depends on the patchset.
   */
  public MessageId fromChangeUpdate(RepoView repoView, PatchSet.Id patchsetId) {
    return fromChangeUpdateAndReason(repoView, patchsetId, null);
  }

  public MessageId fromChangeUpdateAndReason(
      RepoView repoView, PatchSet.Id patchsetId, @Nullable String reason) {
    String suffix = (reason != null) ? ("-" + reason) : "";
    String metaRef = patchsetId.changeId().toRefPrefix() + "meta";
    Optional<ObjectId> metaSha1;
    try {
      metaSha1 = repoView.getRef(metaRef);
    } catch (IOException ex) {
      throw new StorageException("unable to extract info for Message-Id", ex);
    }
    return metaSha1
        .map(optional -> new AutoValue_MessageIdGenerator_MessageId(optional.getName() + suffix))
        .orElseThrow(() -> new IllegalStateException(metaRef + " doesn't exist"));
  }

  public MessageId fromChangeUpdate(Project.NameKey project, PatchSet.Id patchsetId) {
    String metaRef = patchsetId.changeId().toRefPrefix() + "meta";
    Ref ref = getRef(metaRef, project);
    checkState(ref != null, metaRef + " must exist");
    return new AutoValue_MessageIdGenerator_MessageId(ref.getObjectId().getName());
  }

  /**
   * @param accountId Create a {@link MessageId} as a result of an account update.
   * @return MessageId that depends on the account id.
   */
  public MessageId fromAccountUpdate(Account.Id accountId) {
    String userRef = RefNames.refsUsers(accountId);
    Ref ref = getRef(userRef, allUsersName);
    checkState(ref != null, userRef + " must exist");
    return new AutoValue_MessageIdGenerator_MessageId(ref.getObjectId().getName());
  }

  /**
   * Create a {@link MessageId} from a mail message.
   *
   * @param mailMessage The message that was sent but was rejected.
   * @return MessageId that depends on the MailMessage that was rejected.
   */
  public MessageId fromMailMessage(MailMessage mailMessage) {
    return new AutoValue_MessageIdGenerator_MessageId(mailMessage.id() + "-REJECTION");
  }

  /**
   * Create a {@link MessageId} from a reason, Account.Id, and timestamp.
   *
   * @param reason for performing this account update
   * @param accountId
   * @param timestamp
   * @return MessageId that depends on the reason, accountId, and timestamp.
   */
  public MessageId fromReasonAccountIdAndTimestamp(
      String reason, Account.Id accountId, Instant timestamp) {
    return new AutoValue_MessageIdGenerator_MessageId(
        reason + "-" + accountId.toString() + "-" + timestamp.toString());
  }

  private Ref getRef(String userRef, Project.NameKey project) {
    try (Repository repository = repositoryManager.openRepository(project)) {
      return repository.getRefDatabase().findRef(userRef);
    } catch (IOException ex) {
      throw new StorageException("unable to extract info for Message-Id", ex);
    }
  }
}
