// Copyright (C) 2011 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 static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.collect.ImmutableList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

/** Describes the state and edits required to submit a change. */
public class SubmitRecord {
  public static boolean allRecordsOK(Collection<SubmitRecord> in) {
    if (in == null || in.isEmpty()) {
      // If the list is null or empty, it means that this Gerrit installation does not
      // have any form of validation rules.
      // Hence, the permission system should be used to determine if the change can be merged
      // or not.
      return true;
    }

    // The change can be submitted, unless at least one plugin prevents it.
    return in.stream().map(SubmitRecord::status).allMatch(SubmitRecord.Status::allowsSubmission);
  }

  public enum Status {
    // NOTE: These values are persisted in the index, so deleting or changing
    // the name of any values requires a schema upgrade.

    /** The change is ready for submission. */
    OK,

    /** Something is preventing this change from being submitted. */
    NOT_READY,

    /** The change has been closed. */
    CLOSED,

    /** The change was submitted bypassing submit rules. */
    FORCED,

    /**
     * A rule error caused by user misconfiguration.
     *
     * <p>This status should only be used to signal that the user has misconfigured the submit rule.
     * In case plugins encounter server exceptions while evaluating the rule, they should throw a
     * {@link RuntimeException} such as {@link IllegalStateException}.
     *
     * <p>Additional detail may be available in {@link SubmitRecord#errorMessage}.
     */
    RULE_ERROR;

    private boolean allowsSubmission() {
      return this == OK || this == FORCED;
    }
  }

  public Status status;
  public List<Label> labels;
  public List<SubmitRequirement> requirements;
  public String errorMessage;

  public static class Label {
    public enum Status {
      // NOTE: These values are persisted in the index, so deleting or changing
      // the name of any values requires a schema upgrade.

      /**
       * This label provides what is necessary for submission.
       *
       * <p>If provided, {@link Label#appliedBy} describes the user account that applied this label
       * to the change.
       */
      OK,

      /**
       * This label prevents the change from being submitted.
       *
       * <p>If provided, {@link Label#appliedBy} describes the user account that applied this label
       * to the change.
       */
      REJECT,

      /** The label is required for submission, but has not been satisfied. */
      NEED,

      /**
       * The label may be set, but it's neither necessary for submission nor does it block
       * submission if set.
       */
      MAY,

      /**
       * The label is required for submission, but is impossible to complete. The likely cause is
       * access has not been granted correctly by the project owner or site administrator.
       */
      IMPOSSIBLE
    }

    public String label;
    public Status status;
    public Account.Id appliedBy;

    /**
     * Returns a new instance of {@link Label} that contains a new instance for each mutable field.
     */
    public Label deepCopy() {
      Label copy = new Label();
      copy.label = label;
      copy.status = status;
      copy.appliedBy = appliedBy;
      return copy;
    }

    @Override
    public String toString() {
      StringBuilder sb = new StringBuilder();
      sb.append(label).append(": ").append(status);
      if (appliedBy != null) {
        sb.append(" by ").append(appliedBy);
      }
      return sb.toString();
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Label) {
        Label l = (Label) o;
        return Objects.equals(label, l.label)
            && Objects.equals(status, l.status)
            && Objects.equals(appliedBy, l.appliedBy);
      }
      return false;
    }

    @Override
    public int hashCode() {
      return Objects.hash(label, status, appliedBy);
    }
  }

  /**
   * Returns a new instance of {@link SubmitRecord} that contains a new instance for each mutable
   * field.
   */
  public SubmitRecord deepCopy() {
    SubmitRecord copy = new SubmitRecord();
    copy.status = status;
    copy.errorMessage = errorMessage;
    if (labels != null) {
      copy.labels = labels.stream().map(Label::deepCopy).collect(toImmutableList());
    }
    if (requirements != null) {
      copy.requirements = ImmutableList.copyOf(requirements);
    }
    return copy;
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append(status);
    if (status == Status.RULE_ERROR && errorMessage != null) {
      sb.append('(').append(errorMessage).append(')');
    }
    sb.append('[');
    if (labels != null) {
      String delimiter = "";
      for (Label label : labels) {
        sb.append(delimiter).append(label);
        delimiter = ", ";
      }
    }
    sb.append("],[");
    if (requirements != null) {
      String delimiter = "";
      for (SubmitRequirement requirement : requirements) {
        sb.append(delimiter).append(requirement);
        delimiter = ", ";
      }
    }
    sb.append(']');
    return sb.toString();
  }

  @Override
  public boolean equals(Object o) {
    if (o instanceof SubmitRecord) {
      SubmitRecord r = (SubmitRecord) o;
      return Objects.equals(status, r.status)
          && Objects.equals(labels, r.labels)
          && Objects.equals(errorMessage, r.errorMessage)
          && Objects.equals(requirements, r.requirements);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return Objects.hash(status, labels, errorMessage, requirements);
  }

  private Status status() {
    return status;
  }
}
