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

import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.index.Index;
import com.google.gerrit.index.QueryOptions;
import java.util.Collection;
import java.util.List;

/**
 * Wrapper combining an {@link IndexPredicate} together with a {@link DataSource} that returns
 * matching results from the index.
 *
 * <p>Appropriate to return as the rootmost predicate that can be processed using the secondary
 * index; such predicates must also implement {@link DataSource} to be chosen by the query
 * processor.
 *
 * @param <I> The type of the IDs by which the entities are stored in the index.
 * @param <T> The type of the entities that are stored in the index.
 */
public class IndexedQuery<I, T> extends Predicate<T> implements DataSource<T>, Paginated<T> {
  protected final Index<I, T> index;

  private QueryOptions opts;
  private final Predicate<T> pred;
  protected DataSource<T> source;

  public IndexedQuery(Index<I, T> index, Predicate<T> pred, QueryOptions opts)
      throws QueryParseException {
    this.index = index;
    this.opts = opts;
    this.pred = pred;
    this.source = index.getSource(pred, this.opts);
  }

  @Override
  public int getChildCount() {
    return 1;
  }

  @Override
  public Predicate<T> getChild(int i) {
    if (i == 0) {
      return pred;
    }
    throw new ArrayIndexOutOfBoundsException(i);
  }

  @Override
  public List<Predicate<T>> getChildren() {
    return ImmutableList.of(pred);
  }

  @Override
  public QueryOptions getOptions() {
    return opts;
  }

  @Override
  public int getCardinality() {
    return source != null ? source.getCardinality() : opts.limit();
  }

  @Override
  public ResultSet<T> read() {
    return source.read();
  }

  @Override
  public ResultSet<FieldBundle> readRaw() {
    return source.readRaw();
  }

  @Override
  public ResultSet<T> restart(int start, int pageSize) {
    opts = opts.withStart(start).withPageSize(pageSize);
    return search();
  }

  @Override
  public ResultSet<T> restart(Object searchAfter, int pageSize) {
    opts = opts.withSearchAfter(searchAfter).withPageSize(pageSize);
    return search();
  }

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

  @Override
  public int hashCode() {
    return pred.hashCode();
  }

  @Override
  public boolean equals(Object other) {
    if (other == null || getClass() != other.getClass()) {
      return false;
    }
    IndexedQuery<?, ?> o = (IndexedQuery<?, ?>) other;
    return pred.equals(o.pred) && opts.equals(o.opts);
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper("index").add("p", pred).add("opts", opts).toString();
  }

  private ResultSet<T> search() {
    try {
      source = index.getSource(pred, opts);
    } catch (QueryParseException e) {
      // Don't need to show this exception to the user; the only thing that
      // changed about pred was its start, and any other QPEs that might happen
      // should have already thrown from the constructor.
      throw new StorageException(e);
    }
    // Don't convert start to a limit, since the caller of this method (see
    // AndSource) has calculated the actual number to skip.
    return read();
  }
}
