// 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.server.query;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Function;
import com.google.common.base.Throwables;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
import com.google.gwtorm.server.ResultSet;

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

public class AndSource<T> extends AndPredicate<T>
    implements DataSource<T>, Comparator<Predicate<T>> {
  protected final DataSource<T> source;

  private final IsVisibleToPredicate<T> isVisibleToPredicate;
  private final int start;
  private final int cardinality;

  public AndSource(Collection<? extends Predicate<T>> that) {
    this(that, null, 0);
  }

  public AndSource(Predicate<T> that,
      IsVisibleToPredicate<T> isVisibleToPredicate) {
    this(that, isVisibleToPredicate, 0);
  }

  public AndSource(Predicate<T> that,
      IsVisibleToPredicate<T> isVisibleToPredicate, int start) {
    this(ImmutableList.of(that), isVisibleToPredicate, start);
  }

  public AndSource(Collection<? extends Predicate<T>> that,
      IsVisibleToPredicate<T> isVisibleToPredicate, int start) {
    super(that);
    checkArgument(start >= 0, "negative start: %s", start);
    this.isVisibleToPredicate = isVisibleToPredicate;
    this.start = start;

    int c = Integer.MAX_VALUE;
    DataSource<T> s = null;
    int minCost = Integer.MAX_VALUE;
    for (Predicate<T> p : sort(getChildren())) {
      if (p instanceof DataSource) {
        c = Math.min(c, ((DataSource<?>) p).getCardinality());

        int cost = p.estimateCost();
        if (cost < minCost) {
          s = toDataSource(p);
          minCost = cost;
        }
      }
    }
    this.source = s;
    this.cardinality = c;
  }

  @Override
  public ResultSet<T> read() throws OrmException {
    try {
      return readImpl();
    } catch (OrmRuntimeException err) {
      Throwables.propagateIfInstanceOf(err.getCause(), OrmException.class);
      throw new OrmException(err);
    }
  }

  private ResultSet<T> readImpl() throws OrmException {
    if (source == null) {
      throw new OrmException("No DataSource: " + this);
    }
    List<T> r = new ArrayList<>();
    T last = null;
    int nextStart = 0;
    boolean skipped = false;
    for (T data : buffer(source.read())) {
      if (!isMatchable() || match(data)) {
        r.add(data);
      } else {
        skipped = true;
      }
      last = data;
      nextStart++;
    }

    if (skipped && last != null && source instanceof Paginated) {
      // If our source is a paginated source and we skipped at
      // least one of its results, we may not have filled the full
      // limit the caller wants.  Restart the source and continue.
      //
      @SuppressWarnings("unchecked")
      Paginated<T> p = (Paginated<T>) source;
      while (skipped && r.size() < p.getOptions().limit() + start) {
        skipped = false;
        ResultSet<T> next = p.restart(nextStart);

        for (T data : buffer(next)) {
          if (match(data)) {
            r.add(data);
          } else {
            skipped = true;
          }
          nextStart++;
        }
      }
    }

    if (start >= r.size()) {
      r = ImmutableList.of();
    } else if (start > 0) {
      r = ImmutableList.copyOf(r.subList(start, r.size()));
    }
    return new ListResultSet<>(r);
  }

  @Override
  public boolean isMatchable() {
    return isVisibleToPredicate != null || super.isMatchable();
  }

  @Override
  public boolean match(T object) throws OrmException {
    if (isVisibleToPredicate != null && !isVisibleToPredicate.match(object)) {
      return false;
    }

    if (super.isMatchable() && !super.match(object)) {
      return false;
    }

    return true;
  }

  private Iterable<T> buffer(ResultSet<T> scanner) {
    return FluentIterable.from(Iterables.partition(scanner, 50))
        .transformAndConcat(new Function<List<T>, List<T>>() {
          @Override
          public List<T> apply(List<T> buffer) {
            return transformBuffer(buffer);
          }
        });
  }

  protected List<T> transformBuffer(List<T> buffer) throws OrmRuntimeException {
    return buffer;
  }

  @Override
  public int getCardinality() {
    return cardinality;
  }

  private List<Predicate<T>> sort(Collection<? extends Predicate<T>> that) {
    List<Predicate<T>> r = new ArrayList<>(that);
    Collections.sort(r, this);
    return r;
  }

  @Override
  public int compare(Predicate<T> a, Predicate<T> b) {
    int ai = a instanceof DataSource ? 0 : 1;
    int bi = b instanceof DataSource ? 0 : 1;
    int cmp = ai - bi;

    if (cmp == 0) {
      cmp = a.estimateCost() - b.estimateCost();
    }

    if (cmp == 0
        && a instanceof DataSource
        && b instanceof DataSource) {
      DataSource<?> as = (DataSource<?>) a;
      DataSource<?> bs = (DataSource<?>) b;
      cmp = as.getCardinality() - bs.getCardinality();
    }
    return cmp;
  }

  @SuppressWarnings("unchecked")
  private DataSource<T> toDataSource(Predicate<T> pred) {
    return (DataSource<T>) pred;
  }
}
