// Copyright (C) 2013 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.extensions.api.changes;

import static com.google.gerrit.extensions.client.ReviewerState.CC;
import static com.google.gerrit.extensions.client.ReviewerState.REVIEWER;

import com.google.gerrit.extensions.client.Comment;
import com.google.gerrit.extensions.client.ReviewerState;
import com.google.gerrit.extensions.common.FixSuggestionInfo;
import com.google.gerrit.extensions.restapi.DefaultInput;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/** Input passed to {@code POST /changes/[id]/revisions/[id]/review}. */
public class ReviewInput {
  @DefaultInput public String message;

  public String tag;

  public Map<String, Short> labels;
  public Map<String, List<CommentInput>> comments;
  public Map<String, List<RobotCommentInput>> robotComments;

  /**
   * How to process draft comments already in the database that were not also described in this
   * input request.
   *
   * <p>If not set, the default is {@link DraftHandling#KEEP}. If {@link #onBehalfOf} is set, then
   * no other value besides {@code KEEP} is allowed.
   */
  public DraftHandling drafts;

  /** A list of draft IDs that should be published. */
  public List<String> draftIdsToPublish;

  /** Who to send email notifications to after review is stored. */
  public NotifyHandling notify;

  public Map<RecipientType, NotifyInfo> notifyDetails;

  /** If true check to make sure that the comments being posted aren't already present. */
  public boolean omitDuplicateComments;

  /**
   * Account ID, name, email address or username of another user. The review will be posted/updated
   * on behalf of this named user instead of the caller. Caller must have the labelAs-$NAME
   * permission granted for each label that appears in {@link #labels}. This is in addition to the
   * named user also needing to have permission to use the labels.
   */
  public String onBehalfOf;

  /** Reviewers that should be added to this change or removed from it. */
  public List<ReviewerInput> reviewers;

  /**
   * If true mark the change as work in progress. It is an error for both {@link #workInProgress}
   * and {@link #ready} to be true.
   */
  public boolean workInProgress;

  /**
   * If true mark the change as ready for review. It is an error for both {@link #workInProgress}
   * and {@link #ready} to be true.
   */
  public boolean ready;

  /** Users that should be added to the attention set of this change. */
  public List<AttentionSetInput> addToAttentionSet;

  /** Users that should be removed from the attention set of this change. */
  public List<AttentionSetInput> removeFromAttentionSet;

  /**
   * Users in the attention set will only be added and removed based on {@link #addToAttentionSet}
   * and {@link #removeFromAttentionSet}. Normally, they are also added and removed when some events
   * occur. E.g, adding/removing reviewers, marking a change ready for review or work in progress,
   * and replying on changes.
   */
  public boolean ignoreAutomaticAttentionSetRules;

  public enum DraftHandling {
    /** Leave pending drafts alone. */
    KEEP,

    /** Publish pending drafts on this revision only. */
    PUBLISH,

    /** Publish pending drafts on all revisions. */
    PUBLISH_ALL_REVISIONS
  }

  public static class CommentInput extends Comment {
    public Boolean unresolved;
  }

  public static class RobotCommentInput extends Comment {
    public String robotId;
    public String robotRunId;
    public String url;
    public Map<String, String> properties;
    public List<FixSuggestionInfo> fixSuggestions;
  }

  public ReviewInput message(String msg) {
    message = msg != null && !msg.isEmpty() ? msg : null;
    return this;
  }

  public ReviewInput patchSetLevelComment(String message) {
    Objects.requireNonNull(message);
    CommentInput comment = new CommentInput();
    comment.message = message;
    // TODO(davido): Because of cyclic dependency, we cannot use here Patch.PATCHSET_LEVEL constant
    comments = Collections.singletonMap("/PATCHSET_LEVEL", Collections.singletonList(comment));
    return this;
  }

  public ReviewInput label(String name, short value) {
    if (name == null || name.isEmpty()) {
      throw new IllegalArgumentException();
    }
    if (labels == null) {
      labels = new LinkedHashMap<>(4);
    }
    labels.put(name, value);
    return this;
  }

  public ReviewInput label(String name, int value) {
    if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
      throw new IllegalArgumentException();
    }
    return label(name, (short) value);
  }

  public ReviewInput label(String name) {
    return label(name, (short) 1);
  }

  public ReviewInput reviewer(String reviewer) {
    return reviewer(reviewer, REVIEWER, /* confirmed= */ false);
  }

  public ReviewInput cc(String cc) {
    return reviewer(cc, CC, /* confirmed= */ false);
  }

  public ReviewInput reviewer(String reviewer, ReviewerState state, boolean confirmed) {
    ReviewerInput input = new ReviewerInput();
    input.reviewer = reviewer;
    input.state = state;
    input.confirmed = confirmed;
    if (reviewers == null) {
      reviewers = new ArrayList<>();
    }
    reviewers.add(input);
    return this;
  }

  public ReviewInput addUserToAttentionSet(String user, String reason) {
    AttentionSetInput input = new AttentionSetInput();
    input.user = user;
    input.reason = reason;
    if (addToAttentionSet == null) {
      addToAttentionSet = new ArrayList<>();
    }
    addToAttentionSet.add(input);
    return this;
  }

  public ReviewInput removeUserFromAttentionSet(String user, String reason) {
    AttentionSetInput input = new AttentionSetInput();
    input.user = user;
    input.reason = reason;
    if (removeFromAttentionSet == null) {
      removeFromAttentionSet = new ArrayList<>();
    }
    removeFromAttentionSet.add(input);
    return this;
  }

  public ReviewInput blockAutomaticAttentionSetRules() {
    ignoreAutomaticAttentionSetRules = true;
    return this;
  }

  public ReviewInput setWorkInProgress(boolean workInProgress) {
    this.workInProgress = workInProgress;
    ready = !workInProgress;
    return this;
  }

  public ReviewInput setReady(boolean ready) {
    this.ready = ready;
    workInProgress = !ready;
    return this;
  }

  public static ReviewInput recommend() {
    return new ReviewInput().label("Code-Review", 1);
  }

  public static ReviewInput dislike() {
    return new ReviewInput().label("Code-Review", -1);
  }

  public static ReviewInput noScore() {
    return new ReviewInput().label("Code-Review", 0);
  }

  public static ReviewInput approve() {
    return new ReviewInput().label("Code-Review", 2);
  }

  public static ReviewInput reject() {
    return new ReviewInput().label("Code-Review", -2);
  }

  public static ReviewInput create() {
    return new ReviewInput();
  }
}
