// Copyright (C) 2014 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.common;

import com.google.gerrit.common.Nullable;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Objects;

/**
 * Representation of an approval in the REST API.
 *
 * <p>This class determines the JSON format of approvals in the REST API.
 *
 * <p>An approval is a vote of a user for a label on a change.
 */
public class ApprovalInfo extends AccountInfo {
  /**
   * Tag that was set when posting the review that created this approval.
   *
   * <p>Web UIs may use the tag to filter out approvals, e.g. initially hide approvals that have a
   * tag that starts with the {@code autogenerated:} prefix.
   */
  public String tag;

  /**
   * The vote that the user has given for the label.
   *
   * <p>If present and zero, the user is permitted to vote on the label. If absent, the user is not
   * permitted to vote on that label.
   */
  public Integer value;

  /** The time and date describing when the approval was made. */
  // TODO(issue-15508): Migrate timestamp fields in *Info/*Input classes from type Timestamp to
  // Instant
  public Timestamp date;

  /** Whether this vote was made after the change was submitted. */
  public Boolean postSubmit;

  /**
   * The range the user is authorized to vote on that label.
   *
   * <p>If present, the user is permitted to vote on the label regarding the range values. If
   * absent, the user is not permitted to vote on that label.
   */
  public VotingRangeInfo permittedVotingRange;

  public ApprovalInfo(Integer id) {
    super(id);
  }

  public ApprovalInfo(
      Integer id,
      @Nullable Integer value,
      @Nullable VotingRangeInfo permittedVotingRange,
      @Nullable String tag,
      @Nullable Timestamp date) {
    super(id);
    this.value = value;
    this.permittedVotingRange = permittedVotingRange;
    this.date = date;
    this.tag = tag;
  }

  public ApprovalInfo(
      Integer id,
      @Nullable Integer value,
      @Nullable VotingRangeInfo permittedVotingRange,
      @Nullable String tag,
      @Nullable Instant date) {
    super(id);
    this.value = value;
    this.permittedVotingRange = permittedVotingRange;
    this.tag = tag;
    if (date != null) {
      setDate(date);
    }
  }

  // TODO(issue-15508): Migrate timestamp fields in *Info/*Input classes from type Timestamp to
  // Instant
  @SuppressWarnings("JdkObsolete")
  public void setDate(Instant date) {
    this.date = Timestamp.from(date);
  }

  @Override
  public boolean equals(Object o) {
    if (o instanceof ApprovalInfo) {
      ApprovalInfo approvalInfo = (ApprovalInfo) o;
      return super.equals(o)
          && Objects.equals(tag, approvalInfo.tag)
          && Objects.equals(value, approvalInfo.value)
          && Objects.equals(date, approvalInfo.date)
          && Objects.equals(postSubmit, approvalInfo.postSubmit)
          && Objects.equals(permittedVotingRange, approvalInfo.permittedVotingRange);
    }
    return false;
  }

  @Override
  public String toString() {
    return super.toString() + ", value=" + this.value;
  }

  @Override
  public int hashCode() {
    return Objects.hash(super.hashCode(), tag, value, date, postSubmit, permittedVotingRange);
  }
}
