// 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.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.server.ChangeAccess;
import com.google.gerrit.reviewdb.server.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.server.OrmException;
import com.google.gwtorm.server.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, 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);
  }

  @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;
  }

  @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;
  }

  @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:*) B=(branch:*)")
  public Predicate<ChangeData> r05_byBranchOpen(
      @Named("P") final ProjectPredicate p,
      @Named("B") final BranchPredicate b) {
    return new ChangeSource(500) {
      @Override
      ResultSet<Change> scan(ChangeAccess a)
          throws OrmException {
        return a.byBranchOpenAll(
            new Branch.NameKey(p.getValueKey(), b.getValue()));
      }

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

  @Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_after:*) L=(limit:*)")
  public Predicate<ChangeData> r05_byBranchMergedPrev(
      @Named("P") final ProjectPredicate p,
      @Named("B") final BranchPredicate b,
      @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.byBranchClosedPrev(Change.Status.MERGED.getCode(), //
            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
      }

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

  @Rewrite("status:merged P=(project:*) B=(branch:*) S=(sortkey_before:*) L=(limit:*)")
  public Predicate<ChangeData> r05_byBranchMergedNext(
      @Named("P") final ProjectPredicate p,
      @Named("B") final BranchPredicate b,
      @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.byBranchClosedNext(Change.Status.MERGED.getCode(), //
            new Branch.NameKey(p.getValueKey(), b.getValue()), key, limit);
      }

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

  @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));
  }

  @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;
      }
    };
  }

  @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");
    }
  }
}
