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

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.index.change.ChangeField.CHANGE_SPEC;
import static com.google.gerrit.server.index.change.ChangeField.NUMERIC_ID_STR_SPEC;
import static com.google.gerrit.server.index.change.ChangeField.PROJECT_SPEC;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gerrit.entities.Change;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.query.DataSource;
import com.google.gerrit.index.query.IndexPredicate;
import com.google.gerrit.index.query.IndexedQuery;
import com.google.gerrit.index.query.Matchable;
import com.google.gerrit.index.query.Predicate;
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.index.query.ResultSet;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.ChangeDataSource;
import com.google.gerrit.server.query.change.ChangeIndexPostFilterPredicate;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * Wrapper combining an {@link IndexPredicate} together with a {@link ChangeDataSource} 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 ChangeDataSource} to be chosen by the query
 * processor.
 */
public class IndexedChangeQuery extends IndexedQuery<Change.Id, ChangeData>
    implements ChangeDataSource, Matchable<ChangeData> {

  public static QueryOptions createOptions(
      IndexConfig config, int start, int limit, Set<String> fields) {
    return createOptions(config, start, limit, config.pageSizeMultiplier(), limit, fields);
  }

  public static QueryOptions createOptions(
      IndexConfig config,
      int start,
      int pageSize,
      int pageSizeMultiplier,
      int limit,
      Set<String> fields) {
    return createOptions(
        config,
        start,
        pageSize,
        pageSizeMultiplier,
        limit,
        /* allowIncompleteResults= */ false,
        fields);
  }

  public static QueryOptions createOptions(
      IndexConfig config,
      int start,
      int pageSize,
      int pageSizeMultiplier,
      int limit,
      boolean allowIncompleteResults,
      Set<String> fields) {
    // Always include project and change id since both are needed to load the change from NoteDb.
    if (!fields.contains(CHANGE_SPEC.getName())
        && !(fields.contains(PROJECT_SPEC.getName())
            && fields.contains(NUMERIC_ID_STR_SPEC.getName()))) {
      fields = new HashSet<>(fields);
      fields.add(PROJECT_SPEC.getName());
      fields.add(NUMERIC_ID_STR_SPEC.getName());
    }
    return QueryOptions.create(
        config, start, pageSize, pageSizeMultiplier, limit, allowIncompleteResults, fields);
  }

  @VisibleForTesting
  static QueryOptions convertOptions(QueryOptions opts) {
    opts = opts.convertForBackend();
    return IndexedChangeQuery.createOptions(
        opts.config(),
        opts.start(),
        opts.pageSize(),
        opts.pageSizeMultiplier(),
        opts.limit(),
        opts.allowIncompleteResults(),
        opts.fields());
  }

  private final Map<ChangeData, DataSource<ChangeData>> fromSource;

  public IndexedChangeQuery(ChangeIndex index, Predicate<ChangeData> pred, QueryOptions opts)
      throws QueryParseException {
    super(index, pred, convertOptions(opts));
    this.fromSource = new HashMap<>();
  }

  @Override
  public ResultSet<ChangeData> read() {
    final DataSource<ChangeData> currSource = source;
    final ResultSet<ChangeData> rs = currSource.read();

    return new ResultSet<>() {
      @Override
      public Iterator<ChangeData> iterator() {
        return Iterables.transform(
                rs,
                cd -> {
                  fromSource.put(cd, currSource);
                  return cd;
                })
            .iterator();
      }

      @Override
      public ImmutableList<ChangeData> toList() {
        ImmutableList<ChangeData> r = rs.toList();
        for (ChangeData cd : r) {
          fromSource.put(cd, currSource);
        }
        return r;
      }

      @Override
      public void close() {
        rs.close();
      }

      @Override
      public Object searchAfter() {
        return rs.searchAfter();
      }
    };
  }

  public boolean postIndexMatch(Predicate<ChangeData> pred, ChangeData cd) {
    if (pred instanceof ChangeIndexPostFilterPredicate) {
      checkState(
          pred.isMatchable(),
          "match invoked, but child predicate %s doesn't implement %s",
          pred,
          Matchable.class.getName());
      return pred.asMatchable().match(cd);
    }
    for (int i = 0; i < pred.getChildCount(); i++) {
      if (!postIndexMatch(pred.getChild(i), cd)) {
        return false;
      }
    }
    return true;
  }

  @Override
  public boolean match(ChangeData cd) {
    if (index.getIndexFilter().isPresent()) {
      // Evaluate the filter. If we pass the filter, then evaluate everything else.
      if (!index.getIndexFilter().get().match(cd)) {
        return false;
      }
    }
    Predicate<ChangeData> pred = getChild(0);
    if (source != null && fromSource.get(cd) == source && postIndexMatch(pred, cd)) {
      return true;
    }

    checkState(
        pred.isMatchable(),
        "match invoked, but child predicate %s doesn't implement %s",
        pred,
        Matchable.class.getName());
    return pred.asMatchable().match(cd);
  }

  @Override
  public int getCost() {
    // Index queries are assumed to be cheaper than any other type of query, so
    // so try to make sure they get picked. Note that pred's cost may be higher
    // because it doesn't know whether it's being used in an index query or not.
    return 1;
  }

  @Override
  public boolean hasChange() {
    return index.getSchema().hasField(ChangeField.CHANGE_SPEC);
  }
}
