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

import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeAccess;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.query.IntPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryRewriter;
import com.google.gerrit.server.query.RewritePredicate;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.ResultSet;
import com.google.inject.Inject;
import com.google.inject.OutOfScopeException;
import com.google.inject.Provider;
import com.google.inject.name.Named;

import java.util.Collection;

public class ChangeQueryRewriter extends QueryRewriter<ChangeData> {
  private static final QueryRewriter.Definition<ChangeData, ChangeQueryRewriter> mydef =
      new QueryRewriter.Definition<ChangeData, ChangeQueryRewriter>(
          ChangeQueryRewriter.class, new ChangeQueryBuilder(
              new ChangeQueryBuilder.Arguments( //
                  new InvalidProvider<ReviewDb>(), //
                  new InvalidProvider<ChangeQueryRewriter>(), //
                  null, null, null, null, null, null, null, null, null), null));

  private final Provider<ReviewDb> dbProvider;

  @Inject
  ChangeQueryRewriter(Provider<ReviewDb> dbProvider) {
    super(mydef);
    this.dbProvider = dbProvider;
  }

  @Override
  public Predicate<ChangeData> and(Collection<? extends Predicate<ChangeData>> l) {
    return hasSource(l) ? new AndSource(l) : super.and(l);
  }

  @Override
  public Predicate<ChangeData> or(Collection<? extends Predicate<ChangeData>> l) {
    return hasSource(l) ? new OrSource(l) : super.or(l);
  }

  @Rewrite("-status:open")
  @NoCostComputation
  public Predicate<ChangeData> r00_notOpen() {
    return ChangeStatusPredicate.closed(dbProvider);
  }

  @Rewrite("-status:closed")
  @NoCostComputation
  public Predicate<ChangeData> r00_notClosed() {
    return ChangeStatusPredicate.open(dbProvider);
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("-status:merged")
  public Predicate<ChangeData> r00_notMerged() {
    return or(ChangeStatusPredicate.open(dbProvider),
        new ChangeStatusPredicate(dbProvider, Change.Status.ABANDONED));
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("-status:abandoned")
  public Predicate<ChangeData> r00_notAbandoned() {
    return or(ChangeStatusPredicate.open(dbProvider),
        new ChangeStatusPredicate(dbProvider, Change.Status.MERGED));
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("sortkey_before:z A=(age:*)")
  public Predicate<ChangeData> r00_ageToSortKey(@Named("A") AgePredicate a) {
    String cut = ChangeUtil.sortKey(a.getCut(), Integer.MAX_VALUE);
    return and(new SortKeyPredicate.Before(dbProvider, cut), a);
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(limit:*) B=(limit:*)")
  public Predicate<ChangeData> r00_smallestLimit(
      @Named("A") IntPredicate<ChangeData> a,
      @Named("B") IntPredicate<ChangeData> b) {
    return a.intValue() <= b.intValue() ? a : b;
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(sortkey_before:*) B=(sortkey_before:*)")
  public Predicate<ChangeData> r00_oldestSortKey(
      @Named("A") SortKeyPredicate.Before a,
      @Named("B") SortKeyPredicate.Before b) {
    return a.getValue().compareTo(b.getValue()) <= 0 ? a : b;
  }

  @SuppressWarnings("unchecked")
  @NoCostComputation
  @Rewrite("A=(sortkey_after:*) B=(sortkey_after:*)")
  public Predicate<ChangeData> r00_newestSortKey(
      @Named("A") SortKeyPredicate.After a, @Named("B") SortKeyPredicate.After b) {
    return a.getValue().compareTo(b.getValue()) >= 0 ? a : b;
  }

  @Rewrite("status:open P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectOpenPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectOpenPrev(p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() //
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:open P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectOpenNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(500, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectOpenNext(p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() //
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:merged P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectMergedPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedPrev(Change.Status.MERGED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:merged P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectMergedNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedNext(Change.Status.MERGED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:abandoned P=(project:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectAbandonedPrev(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedPrev(Change.Status.ABANDONED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:abandoned P=(project:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r10_byProjectAbandonedNext(
      @Named("P") final ProjectPredicate p,
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(40000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.byProjectClosedNext(Change.Status.ABANDONED.getCode(), //
            p.getValueKey(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && p.match(cd) //
            && s.match(cd);
      }
    };
  }

  @Rewrite("status:open S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byOpenPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allOpenPrev(key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
      }
    };
  }

  @Rewrite("status:open S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byOpenNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(2000, s.getValue(), l.intValue()) {
      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allOpenNext(key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:merged S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byMergedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byMergedPrev", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedPrev(Change.Status.MERGED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:merged S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byMergedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byMergedNext", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedNext(Change.Status.MERGED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.MERGED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:abandoned S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byAbandonedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byAbandonedPrev", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedPrev(Change.Status.ABANDONED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:abandoned S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byAbandonedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return new PaginatedSource(50000, s.getValue(), l.intValue()) {
      {
        init("r20_byAbandonedNext", s, l);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a, String key, int limit)
          throws OrmException {
        return a.allClosedNext(Change.Status.ABANDONED.getCode(), key, limit);
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.ABANDONED
            && s.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byClosedPrev(
      @Named("S") final SortKeyPredicate.After s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return or(r20_byMergedPrev(s, l), r20_byAbandonedPrev(s, l));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r20_byClosedNext(
      @Named("S") final SortKeyPredicate.Before s,
      @Named("L") final IntPredicate<ChangeData> l) {
    return or(r20_byMergedNext(s, l), r20_byAbandonedNext(s, l));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:open O=(owner:*)")
  public Predicate<ChangeData> r25_byOwnerOpen(
      @Named("O") final OwnerPredicate o) {
    return new ChangeSource(50) {
      {
        init("r25_byOwnerOpen", o);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byOwnerOpen(o.getAccountId());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isOpen() && o.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed O=(owner:*)")
  public Predicate<ChangeData> r25_byOwnerClosed(
      @Named("O") final OwnerPredicate o) {
    return new ChangeSource(5000) {
      {
        init("r25_byOwnerClosed", o);
      }

      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byOwnerClosedAll(o.getAccountId());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus().isClosed() && o.match(cd);
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("O=(owner:*)")
  public Predicate<ChangeData> r26_byOwner(@Named("O") OwnerPredicate o) {
    return or(r25_byOwnerOpen(o), r25_byOwnerClosed(o));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:open R=(reviewer:*)")
  public Predicate<ChangeData> r30_byReviewerOpen(
      @Named("R") final ReviewerPredicate r) {
    return new Source() {
      {
        init("r30_byReviewerOpen", r);
      }

      @Override
      public ResultSet<ChangeData> read() throws OrmException {
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
            .patchSetApprovals().openByUser(r.getAccountId()));
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        Change change = cd.change(dbProvider);
        return change != null && change.getStatus().isOpen() && r.match(cd);
      }

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

      @Override
      public int getCost() {
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:closed R=(reviewer:*)")
  public Predicate<ChangeData> r30_byReviewerClosed(
      @Named("R") final ReviewerPredicate r) {
    return new Source() {
      {
        init("r30_byReviewerClosed", r);
      }

      @Override
      public ResultSet<ChangeData> read() throws OrmException {
        return ChangeDataResultSet.patchSetApproval(dbProvider.get()
            .patchSetApprovals().closedByUserAll(r.getAccountId()));
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        Change change = cd.change(dbProvider);
        return change != null && change.getStatus().isClosed() && r.match(cd);
      }

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

      @Override
      public int getCost() {
        return ChangeCosts.cost(ChangeCosts.APPROVALS_SCAN, getCardinality());
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("R=(reviewer:*)")
  public Predicate<ChangeData> r31_byReviewer(
      @Named("R") final ReviewerPredicate r) {
    return or(r30_byReviewerOpen(r), r30_byReviewerClosed(r));
  }

  @SuppressWarnings("unchecked")
  @Rewrite("status:submitted")
  public Predicate<ChangeData> r99_allSubmitted() {
    return new ChangeSource(50) {
      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.allSubmitted();
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return cd.change(dbProvider).getStatus() == Change.Status.SUBMITTED;
      }
    };
  }

  @SuppressWarnings("unchecked")
  @Rewrite("P=(project:*)")
  public Predicate<ChangeData> r99_byProject(
      @Named("P") final ProjectPredicate p) {
    return new ChangeSource(1000000) {
      @Override
      ResultSet<Change> scan(ChangeAccess a) throws OrmException {
        return a.byProject(p.getValueKey());
      }

      @Override
      public boolean match(ChangeData cd) throws OrmException {
        return p.match(cd);
      }
    };
  }

  private static boolean hasSource(Collection<? extends Predicate<ChangeData>> l) {
    for (Predicate<ChangeData> p : l) {
      if (p instanceof ChangeDataSource) {
        return true;
      }
    }
    return false;
  }

  private abstract static class Source extends RewritePredicate<ChangeData>
      implements ChangeDataSource {
    @Override
    public boolean hasChange() {
      return false;
    }
  }

  private abstract class ChangeSource extends Source {
    private final int cardinality;

    ChangeSource(int card) {
      this.cardinality = card;
    }

    abstract ResultSet<Change> scan(ChangeAccess a) throws OrmException;

    @Override
    public ResultSet<ChangeData> read() throws OrmException {
      return ChangeDataResultSet.change(scan(dbProvider.get().changes()));
    }

    @Override
    public boolean hasChange() {
      return true;
    }

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

    @Override
    public int getCost() {
      return ChangeCosts.cost(ChangeCosts.CHANGES_SCAN, getCardinality());
    }
  }

  private abstract class PaginatedSource extends ChangeSource implements
      Paginated {
    private final String startKey;
    private final int limit;

    PaginatedSource(int card, String start, int lim) {
      super(card);
      this.startKey = start;
      this.limit = lim;
    }

    @Override
    public int limit() {
      return limit;
    }

    @Override
    ResultSet<Change> scan(ChangeAccess a) throws OrmException {
      return scan(a, startKey, limit);
    }

    @Override
    public ResultSet<ChangeData> restart(ChangeData last) throws OrmException {
      return ChangeDataResultSet.change(scan(dbProvider.get().changes(), //
          last.change(dbProvider).getSortKey(), //
          limit));
    }

    abstract ResultSet<Change> scan(ChangeAccess a, String key, int limit)
        throws OrmException;
  }

  private static final class InvalidProvider<T> implements Provider<T> {
    @Override
    public T get() {
      throw new OutOfScopeException("Not available at init");
    }
  }
}
