// 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.acceptance.testsuite.change;

import com.google.auto.value.AutoValue;
import com.google.gerrit.acceptance.testsuite.ThrowingFunction;
import com.google.gerrit.acceptance.testsuite.change.TestRange.Position;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.Patch;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Optional;

/**
 * Attributes of the human comment. If not provided, arbitrary values will be used. This class is
 * very similar to {@link TestRobotCommentCreation} to allow separation between robot and human
 * comments.
 */
@AutoValue
public abstract class TestCommentCreation {

  public abstract Optional<String> message();

  public abstract Optional<String> file();

  public abstract Optional<Integer> line();

  public abstract Optional<TestRange> range();

  public abstract Optional<CommentSide> side();

  public abstract Optional<Boolean> unresolved();

  public abstract Optional<String> parentUuid();

  public abstract Optional<String> tag();

  public abstract Optional<Account.Id> author();

  public abstract Optional<Instant> createdOn();

  abstract Comment.Status status();

  abstract ThrowingFunction<TestCommentCreation, String> commentCreator();

  public static Builder builder(
      ThrowingFunction<TestCommentCreation, String> commentCreator, Comment.Status commentStatus) {
    return new AutoValue_TestCommentCreation.Builder()
        .commentCreator(commentCreator)
        .status(commentStatus);
  }

  @AutoValue.Builder
  public abstract static class Builder {

    public Builder noMessage() {
      return message("");
    }

    /** Message text of the comment. */
    public abstract Builder message(String message);

    /** Indicates a patchset-level comment. */
    public Builder onPatchsetLevel() {
      return file(Patch.PATCHSET_LEVEL);
    }

    /** Indicates a file comment. The comment will be on the specified file. */
    public Builder onFileLevelOf(String filePath) {
      return file(filePath).line(null).range(null);
    }

    /**
     * Starts the fluent change to create a line comment. The line comment will be at the indicated
     * line. Lines start with 1.
     */
    public FileBuilder<Builder> onLine(int line) {
      return new FileBuilder<>(file -> file(file).line(line).range(null));
    }

    /**
     * Starts the fluent chain to create a range comment. The range begins at the specified line.
     * Lines start at 1. The start position (line, charOffset) is inclusive, the end position (line,
     * charOffset) is exclusive.
     */
    public PositionBuilder<StartAwarePositionBuilder<Builder>> fromLine(int startLine) {
      return new PositionBuilder<>(
          startCharOffset -> {
            Position start = Position.builder().line(startLine).charOffset(startCharOffset).build();
            TestRange.Builder testRangeBuilder = TestRange.builder().setStart(start);
            return new StartAwarePositionBuilder<>(testRangeBuilder, this::range, this::file);
          });
    }

    /** File on which the comment should be added. */
    abstract Builder file(String filePath);

    /** Line on which the comment should be added. */
    abstract Builder line(@Nullable Integer line);

    /** Range on which the comment should be added. */
    abstract Builder range(@Nullable TestRange range);

    /**
     * Indicates that the comment refers to a file, line, range, ... in the commit of the patchset.
     *
     * <p>On the UI, such comments are shown on the right side of a diff view when a diff against
     * base is selected. See {@link #onParentCommit()} for comments shown on the left side.
     */
    public Builder onPatchsetCommit() {
      return side(CommentSide.PATCHSET_COMMIT);
    }

    /**
     * Indicates that the comment refers to a file, line, range, ... in the parent commit of the
     * patchset.
     *
     * <p>On the UI, such comments are shown on the left side of a diff view when a diff against
     * base is selected. See {@link #onPatchsetCommit()} for comments shown on the right side.
     *
     * <p>For merge commits, this indicates the first parent commit.
     */
    public Builder onParentCommit() {
      return side(CommentSide.PARENT_COMMIT);
    }

    /** Like {@link #onParentCommit()} but for the second parent of a merge commit. */
    public Builder onSecondParentCommit() {
      return side(CommentSide.SECOND_PARENT_COMMIT);
    }

    /**
     * Like {@link #onParentCommit()} but for the AutoMerge commit created from the parents of a
     * merge commit.
     */
    public Builder onAutoMergeCommit() {
      return side(CommentSide.AUTO_MERGE_COMMIT);
    }

    abstract Builder side(CommentSide side);

    /** Indicates a resolved comment. */
    public Builder resolved() {
      return unresolved(false);
    }

    /** Indicates an unresolved comment. */
    public Builder unresolved() {
      return unresolved(true);
    }

    abstract Builder unresolved(boolean unresolved);

    /**
     * UUID of another comment to which this comment is a reply. This comment must have similar
     * attributes (e.g. file, line, side) as the parent comment. The parent comment must be a
     * published comment.
     */
    public abstract Builder parentUuid(String parentUuid);

    /** Tag to attach to the comment. */
    public abstract Builder tag(String value);

    /** Author of the comment. Must be an existing user account. */
    public abstract Builder author(Account.Id accountId);

    /**
     * Creation time of the comment. Like {@link #createdOn(Instant)} but with an arbitrary, fixed
     * time zone (-> deterministic test execution).
     */
    public Builder createdOn(LocalDateTime createdOn) {
      // We don't care about the exact time zone in most tests, just that it's fixed so that tests
      // are deterministic.
      return createdOn(createdOn.atZone(ZoneOffset.UTC).toInstant());
    }

    /**
     * Creation time of the comment. This may also lie in the past or future. Comments stored in
     * NoteDb support only second precision.
     */
    public abstract Builder createdOn(Instant createdOn);

    /**
     * Status of the comment. Hidden in the API surface. Use {@link
     * PerPatchsetOperations#newComment()} or {@link PerPatchsetOperations#newDraftComment()}
     * depending on which type of comment you want to create.
     */
    abstract Builder status(Comment.Status value);

    abstract Builder commentCreator(ThrowingFunction<TestCommentCreation, String> commentCreator);

    abstract TestCommentCreation autoBuild();

    /**
     * Creates the comment.
     *
     * @return the UUID of the created comment
     */
    public String create() {
      TestCommentCreation commentCreation = autoBuild();
      return commentCreation.commentCreator().applyAndThrowSilently(commentCreation);
    }
  }
}
