// 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.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 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, 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);
  }
}
