// 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.PROJECT_SPEC;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
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 oneResult() {
    IndexConfig config = IndexConfig.createDefault();
    return createOptions(config, 0, 1, config.pageSizeMultiplier(), 1, ImmutableSet.of());
  }

  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) {
    // Always include project since it is needed to load the change from NoteDb.
    if (!fields.contains(CHANGE_SPEC.getName()) && !fields.contains(PROJECT_SPEC.getName())) {
      fields = new HashSet<>(fields);
      fields.add(PROJECT_SPEC.getName());
    }
    return QueryOptions.create(config, start, pageSize, pageSizeMultiplier, limit, fields);
  }

  @VisibleForTesting
  static QueryOptions convertOptions(QueryOptions opts) {
    opts = opts.convertForBackend();
    return IndexedChangeQuery.createOptions(
        opts.config(),
        opts.start(),
        opts.pageSize(),
        opts.pageSizeMultiplier(),
        opts.limit(),
        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) {
    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);
  }
}
