// Copyright (C) 2021 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 com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import java.util.Optional;

/** Result of evaluating a submit requirement expression on a given Change. */
@AutoValue
public abstract class SubmitRequirementExpressionResult {

  /** Submit requirement expression for which this result is evaluated. */
  public abstract SubmitRequirementExpression expression();

  /** Status of evaluation. */
  public abstract Status status();

  /**
   * Optional error message. Populated if the evaluator fails to evaluate the expression for a
   * certain change.
   */
  public abstract Optional<String> errorMessage();

  /**
   * List leaf predicates that are fulfilled, for example the expression
   *
   * <p><i>label:code-review=+2 and branch:refs/heads/master</i>
   *
   * <p>has two leaf predicates:
   *
   * <ul>
   *   <li>label:code-review=+2
   *   <li>branch:refs/heads/master
   * </ul>
   *
   * This method will return the leaf predicates that were fulfilled, for example if only the first
   * predicate was fulfilled, the returned list will be equal to ["label:code-review=+2"].
   */
  public abstract ImmutableList<String> passingAtoms();

  /**
   * List of leaf predicates that are not fulfilled. See {@link #passingAtoms()} for more details.
   */
  public abstract ImmutableList<String> failingAtoms();

  public static SubmitRequirementExpressionResult create(
      SubmitRequirementExpression expression, PredicateResult predicateResult) {
    return create(
        expression,
        predicateResult.status() ? Status.PASS : Status.FAIL,
        predicateResult.getPassingAtoms(),
        predicateResult.getFailingAtoms());
  }

  public static SubmitRequirementExpressionResult create(
      SubmitRequirementExpression expression,
      Status status,
      ImmutableList<String> passingAtoms,
      ImmutableList<String> failingAtoms) {
    return new AutoValue_SubmitRequirementExpressionResult(
        expression, status, Optional.empty(), passingAtoms, failingAtoms);
  }

  public static SubmitRequirementExpressionResult error(
      SubmitRequirementExpression expression, String errorMessage) {
    return new AutoValue_SubmitRequirementExpressionResult(
        expression,
        Status.ERROR,
        Optional.of(errorMessage),
        ImmutableList.of(),
        ImmutableList.of());
  }

  public static TypeAdapter<SubmitRequirementExpressionResult> typeAdapter(Gson gson) {
    return new AutoValue_SubmitRequirementExpressionResult.GsonTypeAdapter(gson);
  }

  public enum Status {
    /** Submit requirement expression is fulfilled for a given change. */
    PASS,

    /** Submit requirement expression is failing for a given change. */
    FAIL,

    /** Submit requirement expression contains invalid syntax and is not parsable. */
    ERROR
  }

  /**
   * Entity detailing the result of evaluating a predicate.
   *
   * <p>Example - branch:refs/heads/foo and has:unresolved
   *
   * <p>The above predicate is an "And" predicate having two child predicates:
   *
   * <ul>
   *   <li>branch:refs/heads/foo
   *   <li>has:unresolved
   * </ul>
   *
   * <p>Each child predicate as well as the parent contains the result of its evaluation.
   */
  @AutoValue
  public abstract static class PredicateResult {
    abstract ImmutableList<PredicateResult> childPredicateResults();

    public abstract String predicateString();

    /** true if the predicate is passing for a given change. */
    abstract boolean status();

    /** Returns a list of leaf predicate results whose {@link PredicateResult#status()} is true. */
    ImmutableList<String> getPassingAtoms() {
      return getAtoms(/* status= */ true).stream()
          .map(PredicateResult::predicateString)
          .collect(ImmutableList.toImmutableList());
    }

    /** Returns a list of leaf predicate results whose {@link PredicateResult#status()} is false. */
    ImmutableList<String> getFailingAtoms() {
      return getAtoms(/* status= */ false).stream()
          .map(PredicateResult::predicateString)
          .collect(ImmutableList.toImmutableList());
    }

    /**
     * Returns the list of leaf {@link PredicateResult} whose {@link #status()} is equal to the
     * {@code status} parameter.
     */
    private ImmutableList<PredicateResult> getAtoms(boolean status) {
      ImmutableList.Builder<PredicateResult> atomsList = ImmutableList.builder();
      getAtomsRecursively(atomsList, status);
      return atomsList.build();
    }

    private void getAtomsRecursively(ImmutableList.Builder<PredicateResult> list, boolean status) {
      if (childPredicateResults().isEmpty() && status() == status) {
        list.add(this);
        return;
      }
      childPredicateResults().forEach(c -> c.getAtomsRecursively(list, status));
    }

    public static Builder builder() {
      return new AutoValue_SubmitRequirementExpressionResult_PredicateResult.Builder();
    }

    @AutoValue.Builder
    public abstract static class Builder {
      public abstract Builder childPredicateResults(ImmutableList<PredicateResult> value);

      protected abstract ImmutableList.Builder<PredicateResult> childPredicateResultsBuilder();

      public abstract Builder predicateString(String value);

      public abstract Builder status(boolean value);

      public Builder addChildPredicateResult(PredicateResult result) {
        childPredicateResultsBuilder().add(result);
        return this;
      }

      public abstract PredicateResult build();
    }
  }
}
