// 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.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RevId;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.config.WildProjectName;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.query.IntPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.query.QueryBuilder;
import com.google.gerrit.server.query.QueryParseException;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.lib.AbbreviatedObjectId;

import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Pattern;

/**
 * Parses a query string meant to be applied to change objects.
 */
public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
  private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");
  private static final Pattern PAT_CHANGE_ID =
      Pattern.compile("^[iI][0-9a-f]{4,}.*$");
  private static final Pattern DEF_CHANGE =
      Pattern.compile("^([1-9][0-9]*|[iI][0-9a-f]{4,}.*)$");

  private static final Pattern PAT_COMMIT =
      Pattern.compile("^([0-9a-fA-F]{4," + RevId.LEN + "})$");
  private static final Pattern PAT_EMAIL =
      Pattern.compile("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+");

  private static final Pattern PAT_LABEL =
      Pattern.compile("^[a-zA-Z][a-zA-Z0-9]*((=|>=|<=)[+-]?|[+-])\\d+$");

  public static final String FIELD_AGE = "age";
  public static final String FIELD_BRANCH = "branch";
  public static final String FIELD_CHANGE = "change";
  public static final String FIELD_COMMIT = "commit";
  public static final String FIELD_DRAFTBY = "draftby";
  public static final String FIELD_FILE = "file";
  public static final String FIELD_IS = "is";
  public static final String FIELD_HAS = "has";
  public static final String FIELD_LABEL = "label";
  public static final String FIELD_LIMIT = "limit";
  public static final String FIELD_OWNER = "owner";
  public static final String FIELD_PROJECT = "project";
  public static final String FIELD_REF = "ref";
  public static final String FIELD_REVIEWER = "reviewer";
  public static final String FIELD_STARREDBY = "starredby";
  public static final String FIELD_STATUS = "status";
  public static final String FIELD_TOPIC = "topic";
  public static final String FIELD_TR = "tr";
  public static final String FIELD_VISIBLETO = "visibleto";
  public static final String FIELD_WATCHEDBY = "watchedby";

  private static final QueryBuilder.Definition<ChangeData, ChangeQueryBuilder> mydef =
      new QueryBuilder.Definition<ChangeData, ChangeQueryBuilder>(
          ChangeQueryBuilder.class);

  static class Arguments {
    final Provider<ReviewDb> dbProvider;
    final Provider<ChangeQueryRewriter> rewriter;
    final IdentifiedUser.GenericFactory userFactory;
    final ChangeControl.Factory changeControlFactory;
    final ChangeControl.GenericFactory changeControlGenericFactory;
    final AccountResolver accountResolver;
    final GroupCache groupCache;
    final AuthConfig authConfig;
    final ApprovalTypes approvalTypes;
    final Project.NameKey wildProjectName;
    final PatchListCache patchListCache;

    @Inject
    Arguments(Provider<ReviewDb> dbProvider,
        Provider<ChangeQueryRewriter> rewriter,
        IdentifiedUser.GenericFactory userFactory,
        ChangeControl.Factory changeControlFactory,
        ChangeControl.GenericFactory changeControlGenericFactory,
        AccountResolver accountResolver, GroupCache groupCache,
        AuthConfig authConfig, ApprovalTypes approvalTypes,
        @WildProjectName Project.NameKey wildProjectName,
        PatchListCache patchListCache) {
      this.dbProvider = dbProvider;
      this.rewriter = rewriter;
      this.userFactory = userFactory;
      this.changeControlFactory = changeControlFactory;
      this.changeControlGenericFactory = changeControlGenericFactory;
      this.accountResolver = accountResolver;
      this.groupCache = groupCache;
      this.authConfig = authConfig;
      this.approvalTypes = approvalTypes;
      this.wildProjectName = wildProjectName;
      this.patchListCache = patchListCache;
    }
  }

  public interface Factory {
    ChangeQueryBuilder create(CurrentUser user);
  }

  private final Arguments args;
  private final CurrentUser currentUser;
  private boolean allowsFile;

  @Inject
  ChangeQueryBuilder(Arguments args, @Assisted CurrentUser currentUser) {
    super(mydef);
    this.args = args;
    this.currentUser = currentUser;
  }

  public void setAllowFile(boolean on) {
    allowsFile = on;
  }

  @Operator
  public Predicate<ChangeData> age(String value) {
    return new AgePredicate(args.dbProvider, value);
  }

  @Operator
  public Predicate<ChangeData> change(String query) {
    if (PAT_LEGACY_ID.matcher(query).matches()) {
      return new LegacyChangeIdPredicate(args.dbProvider, Change.Id
          .parse(query));

    } else if (PAT_CHANGE_ID.matcher(query).matches()) {
      if (query.charAt(0) == 'i') {
        query = "I" + query.substring(1);
      }
      return new ChangeIdPredicate(args.dbProvider, query);
    }

    throw new IllegalArgumentException();
  }

  @Operator
  public Predicate<ChangeData> status(String statusName) {
    if ("open".equals(statusName)) {
      return status_open();

    } else if ("closed".equals(statusName)) {
      return ChangeStatusPredicate.closed(args.dbProvider);

    } else if ("reviewed".equalsIgnoreCase(statusName)) {
      return new IsReviewedPredicate(args.dbProvider);

    } else {
      return new ChangeStatusPredicate(args.dbProvider, statusName);
    }
  }

  public Predicate<ChangeData> status_open() {
    return ChangeStatusPredicate.open(args.dbProvider);
  }

  @Operator
  public Predicate<ChangeData> has(String value) {
    if ("star".equalsIgnoreCase(value)) {
      return new IsStarredByPredicate(args.dbProvider, currentUser);
    }

    if ("draft".equalsIgnoreCase(value)) {
      if (currentUser instanceof IdentifiedUser) {
        return new HasDraftByPredicate(args.dbProvider,
            ((IdentifiedUser) currentUser).getAccountId());
      }
    }

    throw new IllegalArgumentException();
  }

  @Operator
  public Predicate<ChangeData> is(String value) {
    if ("starred".equalsIgnoreCase(value)) {
      return new IsStarredByPredicate(args.dbProvider, currentUser);
    }

    if ("watched".equalsIgnoreCase(value)) {
      return new IsWatchedByPredicate(args, currentUser);
    }

    if ("visible".equalsIgnoreCase(value)) {
      return is_visible();
    }

    if ("reviewed".equalsIgnoreCase(value)) {
      return new IsReviewedPredicate(args.dbProvider);
    }

    try {
      return status(value);
    } catch (IllegalArgumentException e) {
      // not status: alias?
    }

    throw new IllegalArgumentException();
  }

  @Operator
  public Predicate<ChangeData> commit(String id) {
    return new CommitPredicate(args.dbProvider, AbbreviatedObjectId
        .fromString(id));
  }

  @Operator
  public Predicate<ChangeData> project(String name) {
    return new ProjectPredicate(args.dbProvider, name);
  }

  @Operator
  public Predicate<ChangeData> branch(String name) {
    return new BranchPredicate(args.dbProvider, name);
  }

  @Operator
  public Predicate<ChangeData> topic(String name) {
    return new TopicPredicate(args.dbProvider, name);
  }

  @Operator
  public Predicate<ChangeData> ref(String ref) {
    return new RefPredicate(args.dbProvider, ref);
  }

  @Operator
  public Predicate<ChangeData> file(String file) throws QueryParseException {
    if (!allowsFile) {
      throw error("operator not permitted here: file:" + file);
    }

    if (file.startsWith("^")) {
      return new RegexFilePredicate(args.dbProvider, args.patchListCache, file);
    }

    throw new IllegalArgumentException();
  }

  @Operator
  public Predicate<ChangeData> label(String name) {
    return new LabelPredicate(args.changeControlGenericFactory,
        args.userFactory, args.dbProvider, args.approvalTypes, name);
  }

  @Operator
  public Predicate<ChangeData> starredby(String who)
      throws QueryParseException, OrmException {
    Account account = args.accountResolver.find(who);
    if (account == null) {
      throw error("User " + who + " not found");
    }
    return new IsStarredByPredicate(args.dbProvider, //
        args.userFactory.create(args.dbProvider, account.getId()));
  }

  @Operator
  public Predicate<ChangeData> watchedby(String who)
      throws QueryParseException, OrmException {
    Account account = args.accountResolver.find(who);
    if (account == null) {
      throw error("User " + who + " not found");
    }
    return new IsWatchedByPredicate(args, args.userFactory.create(
        args.dbProvider, account.getId()));
  }

  @Operator
  public Predicate<ChangeData> draftby(String who) throws QueryParseException,
      OrmException {
    Account account = args.accountResolver.find(who);
    if (account == null) {
      throw error("User " + who + " not found");
    }
    return new HasDraftByPredicate(args.dbProvider, account.getId());
  }

  @Operator
  public Predicate<ChangeData> visibleto(String who)
      throws QueryParseException, OrmException {
    Account account = args.accountResolver.find(who);
    if (account != null) {
      return visibleto(args.userFactory
          .create(args.dbProvider, account.getId()));
    }

    // If its not an account, maybe its a group?
    //
    AccountGroup g = args.groupCache.get(new AccountGroup.NameKey(who));
    if (g != null) {
      return visibleto(new SingleGroupUser(args.authConfig, g.getId()));
    }

    Collection<AccountGroup> matches =
        args.groupCache.get(new AccountGroup.ExternalNameKey(who));
    if (matches != null && !matches.isEmpty()) {
      HashSet<AccountGroup.Id> ids = new HashSet<AccountGroup.Id>();
      for (AccountGroup group : matches) {
        ids.add(group.getId());
      }
      return visibleto(new SingleGroupUser(args.authConfig, ids));
    }

    throw error("No user or group matches \"" + who + "\".");
  }

  public Predicate<ChangeData> visibleto(CurrentUser user) {
    return new IsVisibleToPredicate(args.dbProvider, //
        args.changeControlGenericFactory, //
        user);
  }

  public Predicate<ChangeData> is_visible() {
    return visibleto(currentUser);
  }

  @Operator
  public Predicate<ChangeData> owner(String who) throws QueryParseException,
      OrmException {
    Account account = args.accountResolver.find(who);
    if (account == null) {
      throw error("User " + who + " not found");
    }
    return new OwnerPredicate(args.dbProvider, account.getId());
  }

  @Operator
  public Predicate<ChangeData> reviewer(String nameOrEmail)
      throws QueryParseException, OrmException {
    Account account = args.accountResolver.find(nameOrEmail);
    if (account == null) {
      throw error("Reviewer " + nameOrEmail + " not found");
    }
    return new ReviewerPredicate(args.dbProvider, account.getId());
  }

  @Operator
  public Predicate<ChangeData> tr(String trackingId) {
    return new TrackingIdPredicate(args.dbProvider, trackingId);
  }

  @Operator
  public Predicate<ChangeData> bug(String trackingId) {
    return tr(trackingId);
  }

  @Operator
  public Predicate<ChangeData> limit(String limit) {
    return limit(Integer.parseInt(limit));
  }

  public Predicate<ChangeData> limit(int limit) {
    return new IntPredicate<ChangeData>(FIELD_LIMIT, limit) {
      @Override
      public boolean match(ChangeData object) {
        return true;
      }

      @Override
      public int getCost() {
        return 0;
      }
    };
  }

  @Operator
  public Predicate<ChangeData> sortkey_after(String sortKey) {
    return new SortKeyPredicate.After(args.dbProvider, sortKey);
  }

  @Operator
  public Predicate<ChangeData> sortkey_before(String sortKey) {
    return new SortKeyPredicate.Before(args.dbProvider, sortKey);
  }

  @Operator
  public Predicate<ChangeData> resume_sortkey(String sortKey) {
    return sortkey_before(sortKey);
  }

  @SuppressWarnings("unchecked")
  public boolean hasLimit(Predicate<ChangeData> p) {
    return find(p, IntPredicate.class, FIELD_LIMIT) != null;
  }

  @SuppressWarnings("unchecked")
  public int getLimit(Predicate<ChangeData> p) {
    return ((IntPredicate) find(p, IntPredicate.class, FIELD_LIMIT)).intValue();
  }

  @SuppressWarnings("unchecked")
  public boolean hasSortKey(Predicate<ChangeData> p) {
    return find(p, SortKeyPredicate.class, "sortkey_after") != null
        || find(p, SortKeyPredicate.class, "sortkey_before") != null;
  }

  @SuppressWarnings("unchecked")
  @Override
  protected Predicate<ChangeData> defaultField(String query)
      throws QueryParseException {
    if (query.startsWith("refs/")) {
      return ref(query);

    } else if (DEF_CHANGE.matcher(query).matches()) {
      return change(query);

    } else if (PAT_COMMIT.matcher(query).matches()) {
      return commit(query);

    } else if (PAT_EMAIL.matcher(query).find()) {
      try {
        return Predicate.or(owner(query), reviewer(query));
      } catch (OrmException err) {
        throw error("Cannot lookup user", err);
      }

    } else if (PAT_LABEL.matcher(query).find()) {
      return label(query);

    } else {
      throw error("Unsupported query:" + query);
    }
  }
}
