// Copyright (C) 2009 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.server.query;

import com.google.common.collect.Iterables;
import com.google.gwtorm.server.OrmException;

import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * An abstract predicate tree for any form of query.
 * <p>
 * Implementations should be immutable, such that the meaning of a predicate
 * never changes once constructed. They should ensure their immutable promise by
 * defensively copying any structures which might be modified externally, but
 * was passed into the object's constructor.
 * <p>
 * However, implementations <i>may</i> retain non-thread-safe caches internally,
 * to speed up evaluation operations within the context of one thread's
 * evaluation of the predicate. As a result, callers should assume predicates
 * are not thread-safe, but that two predicate graphs produce the same results
 * given the same inputs if they are {@link #equals(Object)}.
 * <p>
 * Predicates should support deep inspection whenever possible, so that generic
 * algorithms can be written to operate against them. Predicates which contain
 * other predicates should override {@link #getChildren()} to return the list of
 * children nested within the predicate.
 *
 * @param <T> type of object the predicate can evaluate in memory.
 */
public abstract class Predicate<T> {
  /** A predicate that matches any input, always, with no cost. */
  @SuppressWarnings("unchecked")
  public static <T> Predicate<T> any() {
    return (Predicate<T>) Any.INSTANCE;
  }

  /** Combine the passed predicates into a single AND node. */
  @SafeVarargs
  public static <T> Predicate<T> and(final Predicate<T>... that) {
    if (that.length == 1) {
      return that[0];
    }
    return new AndPredicate<>(that);
  }

  /** Combine the passed predicates into a single AND node. */
  public static <T> Predicate<T> and(
      final Collection<? extends Predicate<T>> that) {
    if (that.size() == 1) {
      return Iterables.getOnlyElement(that);
    }
    return new AndPredicate<>(that);
  }

  /** Combine the passed predicates into a single OR node. */
  @SafeVarargs
  public static <T> Predicate<T> or(final Predicate<T>... that) {
    if (that.length == 1) {
      return that[0];
    }
    return new OrPredicate<>(that);
  }

  /** Combine the passed predicates into a single OR node. */
  public static <T> Predicate<T> or(
      final Collection<? extends Predicate<T>> that) {
    if (that.size() == 1) {
      return Iterables.getOnlyElement(that);
    }
    return new OrPredicate<>(that);
  }

  /** Invert the passed node. */
  public static <T> Predicate<T> not(final Predicate<T> that) {
    if (that instanceof NotPredicate) {
      // Negate of a negate is the original predicate.
      //
      return that.getChild(0);
    }
    return new NotPredicate<>(that);
  }

  /** Get the children of this predicate, if any. */
  public List<Predicate<T>> getChildren() {
    return Collections.emptyList();
  }

  /** Same as {@code getChildren().size()} */
  public int getChildCount() {
    return getChildren().size();
  }

  /** Same as {@code getChildren().get(i)} */
  public Predicate<T> getChild(final int i) {
    return getChildren().get(i);
  }

  /** Create a copy of this predicate, with new children. */
  public abstract Predicate<T> copy(Collection<? extends Predicate<T>> children);

  /**
   * Does this predicate match this object?
   *
   * @throws OrmException
   */
  public abstract boolean match(T object) throws OrmException;

  /** @return a cost estimate to run this predicate, higher figures cost more. */
  public abstract int getCost();

  @Override
  public abstract int hashCode();

  @Override
  public abstract boolean equals(Object other);

  private static class Any<T> extends Predicate<T> {
    private static final Any<Object> INSTANCE = new Any<>();

    private Any() {
    }

    @Override
    public Predicate<T> copy(Collection<? extends Predicate<T>> children) {
      return this;
    }

    @Override
    public boolean match(T object) {
      return true;
    }

    @Override
    public int getCost() {
      return 0;
    }

    @Override
    public int hashCode() {
      return System.identityHashCode(this);
    }

    @Override
    public boolean equals(Object other) {
      return other == this;
    }
  }
}
