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

import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.index.query.PostFilterPredicate;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData.StorageConstraint;
import java.io.IOException;
import java.util.Optional;
import org.eclipse.jgit.errors.ConfigInvalidException;

public class EqualsLabelPredicates {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public static class PostFilterEqualsLabelPredicate extends PostFilterPredicate<ChangeData> {
    private final Matcher matcher;

    public PostFilterEqualsLabelPredicate(
        LabelPredicate.Args args, String label, int expVal, @Nullable Integer count) {
      super(ChangeQueryBuilder.FIELD_LABEL, ChangeField.formatLabel(label, expVal, count));
      matcher = new Matcher(args, label, expVal, count);
    }

    @Override
    public boolean match(ChangeData object) {
      return matcher.match(object);
    }

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

  public static class IndexEqualsLabelPredicate extends ChangeIndexPostFilterPredicate {
    private final Matcher matcher;

    public IndexEqualsLabelPredicate(
        LabelPredicate.Args args, String label, int expVal, @Nullable Integer count) {
      this(args, label, expVal, null, count);
    }

    public IndexEqualsLabelPredicate(
        LabelPredicate.Args args,
        String label,
        int expVal,
        @Nullable Account.Id account,
        @Nullable Integer count) {
      super(ChangeField.LABEL_SPEC, ChangeField.formatLabel(label, expVal, account, count));
      this.matcher = new Matcher(args, label, expVal, account, count);
    }

    @Override
    public boolean match(ChangeData object) {
      return matcher.match(object);
    }

    @Override
    public int getCost() {
      return 1 + (matcher.group == null ? 0 : 1);
    }
  }

  private static class Matcher {
    protected final AccountResolver accountResolver;
    protected final ProjectCache projectCache;
    protected final PermissionBackend permissionBackend;
    protected final IdentifiedUser.GenericFactory userFactory;

    /** label name to be matched. */
    protected final String label;

    /** Expected vote value for the label. */
    protected final int expVal;

    /**
     * Number of times the value {@link #expVal} for label {@link #label} should occur. If null,
     * match with any count greater or equal to 1.
     */
    @Nullable protected final Integer count;

    /** Account ID that has voted on the label. */
    @Nullable protected final Account.Id account;

    protected final AccountGroup.UUID group;

    public Matcher(LabelPredicate.Args args, String label, int expVal, @Nullable Integer count) {
      this(args, label, expVal, null, count);
    }

    public Matcher(
        LabelPredicate.Args args,
        String label,
        int expVal,
        @Nullable Account.Id account,
        @Nullable Integer count) {
      this.permissionBackend = args.permissionBackend;
      this.accountResolver = args.accountResolver;
      this.projectCache = args.projectCache;
      this.userFactory = args.userFactory;
      this.group = args.group;
      this.label = label;
      this.expVal = expVal;
      this.account = account;
      this.count = count;
    }

    public boolean match(ChangeData cd) {
      Change c = cd.change();
      if (c == null) {
        // The change has disappeared.
        logger.atFine().log(
            "%s=%s doesn't match because the change has disappeared.", label, expVal);
        return false;
      }

      if (Integer.valueOf(0).equals(count)) {
        // We don't match against count=0 so that the computation is identical to the stored values
        // in the index. We do that since computing count=0 requires looping on all {label_type,
        // vote_value} for the change and storing a {count=0} format for it in the change index
        // which is computationally expensive.
        logger.atFine().log(
            "%s=%s doesn't match change %s because the count was specified as 0 which is not"
                + " supported.",
            label, expVal, cd.change().getChangeId());
        return false;
      }

      Optional<ProjectState> project = projectCache.get(c.getDest().project());
      if (!project.isPresent()) {
        // The project has disappeared.
        logger.atFine().log(
            "%s=%s doesn't match change %s because its project %s has disappeared.",
            label, expVal, cd.change().getChangeId(), c.getDest().project().get());
        return false;
      }

      LabelType labelType = type(project.get().getLabelTypes(), label);
      if (labelType == null) {
        logger.atFine().log(
            "%s=%s doesn't match change %s because the label is not defined by its project %s"
                + " (label type = %s)",
            label, expVal, cd.change().getChangeId(), project.get(), project.get().getLabelTypes());
        return false; // Label is not defined by this project.
      }

      boolean hasVote = false;
      int matchingVotes = 0;
      StorageConstraint currentStorageConstraint = cd.getStorageConstraint();
      cd.setStorageConstraint(ChangeData.StorageConstraint.INDEX_PRIMARY_NOTEDB_SECONDARY);
      for (PatchSetApproval psa : cd.currentApprovals()) {
        if (labelType.matches(psa)) {
          hasVote = true;
          if (match(cd, psa)) {
            matchingVotes += 1;
          }
        }
      }
      logger.atFine().log(
          "found %s matching votes for %s=%s on change %s (current approvals = %s)",
          matchingVotes, label, expVal, cd.change().getChangeId(), cd.currentApprovals());
      cd.setStorageConstraint(currentStorageConstraint);
      if (!hasVote && expVal == 0) {
        logger.atFine().log(
            "%s=%s matches change %s because there is no vote for label %s",
            label, expVal, cd.change().getChangeId(), label);
        return true;
      }

      if (count == null) {
        if (matchingVotes >= 1) {
          logger.atFine().log(
              "%s=%s matches change %s because there are %s matching votes (count was not"
                  + " specified, hence 1 or more votes are needed)",
              label, expVal, cd.change().getChangeId(), matchingVotes);
          return true;
        }
        logger.atFine().log(
            "%s=%s doesn't match change %s because there are no matching votes (count was not"
                + " specified, hence 1 or more votes are needed)",
            label, expVal, cd.change().getChangeId());
        return false;
      }

      if (matchingVotes == count) {
        logger.atFine().log(
            "%s=%s matches change %s because there are %s matching votes which matches the"
                + " expected count %s",
            label, expVal, cd.change().getChangeId(), matchingVotes, count);
        return true;
      }
      logger.atFine().log(
          "%s=%s doesn't match change %s because there are %s matching votes which doesn't match"
              + " the expected count %s",
          label, expVal, cd.change().getChangeId(), matchingVotes, count);
      return false;
    }

    private boolean match(ChangeData cd, PatchSetApproval psa) {
      if (psa.value() != expVal) {
        logger.atFine().log(
            "vote %s on change %s doesn't match expected value %s",
            psa, cd.change().getChangeId(), expVal);
        return false;
      }
      Account.Id approver = psa.accountId();

      if (account != null) {
        // case when account in query is numeric
        if (!account.equals(approver) && !isMagicUser()) {
          logger.atFine().log(
              "vote %s on change %s doesn't match expected approver %s",
              psa, cd.change().getChangeId(), account);
          return false;
        }

        // case when account in query = owner
        if (account.equals(ChangeQueryBuilder.OWNER_ACCOUNT_ID)
            && !cd.change().getOwner().equals(approver)) {
          logger.atFine().log(
              "vote %s on change %s doesn't match since it is not from the change owner %s",
              psa, cd.change().getChangeId(), cd.change().getOwner());
          return false;
        }

        // case when account in query = non_uploader
        if (account.equals(ChangeQueryBuilder.NON_UPLOADER_ACCOUNT_ID)
            && cd.currentPatchSet().uploader().equals(approver)) {
          logger.atFine().log(
              "vote %s on change %s doesn't match since it is from the uploader %s",
              psa, cd.change().getChangeId(), cd.currentPatchSet().uploader());
          return false;
        }

        if (account.equals(ChangeQueryBuilder.NON_CONTRIBUTOR_ACCOUNT_ID)) {
          if (cd.currentPatchSet().uploader().equals(approver)
              || matchAccount(cd.getCommitter().getEmailAddress(), approver)
              || matchAccount(cd.getAuthor().getEmailAddress(), approver)) {
            logger.atFine().log(
                "vote %s on change %s doesn't match since it is from a contributor"
                    + " (uploader: %s, committer: %s, author: %s)",
                psa,
                cd.change().getChangeId(),
                cd.currentPatchSet().uploader(),
                cd.getCommitter().getEmailAddress(),
                cd.getAuthor().getEmailAddress());
            return false;
          }
        }

        if (account.equals(ChangeQueryBuilder.NON_AUTHOR_ACCOUNT_ID)) {
          if (matchAccount(cd.getAuthor().getEmailAddress(), approver)) {
            logger.atFine().log(
                "vote %s on change %s doesn't match since it is from the author %s",
                psa, cd.change().getChangeId(), cd.getAuthor().getEmailAddress());
            return false;
          }
        }

        if (account.equals(ChangeQueryBuilder.NON_COMMITTER_ACCOUNT_ID)) {
          if (matchAccount(cd.getCommitter().getEmailAddress(), approver)) {
            logger.atFine().log(
                "vote %s on change %s doesn't match since it is from the committer %s",
                psa, cd.change().getChangeId(), cd.getCommitter().getEmailAddress());
            return false;
          }
        }
      }

      IdentifiedUser reviewer = userFactory.create(approver);
      if (group != null && !reviewer.getEffectiveGroups().contains(group)) {
        logger.atFine().log(
            "vote %s on change %s doesn't match since the approver %s is not a member of the"
                + " expected group %s",
            psa, cd.change().getChangeId(), approver, group);
        return false;
      }

      // Check the user has 'READ' permission.
      PermissionBackend.ForChange perm = permissionBackend.absentUser(approver).change(cd);
      if (!cd.projectStatePermitsRead()) {
        logger.atFine().log(
            "vote %s on change %s doesn't match since the project %s doesn't permit read",
            psa, cd.change().getChangeId(), cd.project().get());
        return false;
      }
      try {
        if (perm.test(ChangePermission.READ)) {
          logger.atFine().log("vote %s on change %s matches", psa, cd.change().getChangeId());
          return true;
        }
        logger.atFine().log(
            "vote %s on change %s doesn't match because the approver %s has no read access",
            psa, cd.change().getChangeId(), approver);
        return false;
      } catch (PermissionBackendException e) {
        logger.atFine().log(
            "vote %s on change %s doesn't match because we failed to compute if the approver %s has"
                + " read access",
            psa, cd.change().getChangeId(), approver);
        return false;
      }
    }

    /**
     * Returns true if the {@code email} parameter belongs to the account identified by the {@code
     * accountId} parameter.
     */
    private boolean matchAccount(String email, Account.Id accountId) {
      try {
        ImmutableList<AccountState> accountsList = accountResolver.resolve(email).asList();
        return accountsList.stream().anyMatch(c -> c.account().id().equals(accountId));
      } catch (ConfigInvalidException | IOException e) {
        logger.atWarning().withCause(e).log("Failed to resolve account %s", email);
      }
      return false;
    }

    private boolean isMagicUser() {
      return account != null
          && (account.equals(ChangeQueryBuilder.OWNER_ACCOUNT_ID)
              || account.equals(ChangeQueryBuilder.NON_UPLOADER_ACCOUNT_ID)
              || account.equals(ChangeQueryBuilder.NON_CONTRIBUTOR_ACCOUNT_ID)
              || account.equals(ChangeQueryBuilder.NON_AUTHOR_ACCOUNT_ID)
              || account.equals(ChangeQueryBuilder.NON_COMMITTER_ACCOUNT_ID));
    }
  }

  @Nullable
  public static LabelType type(LabelTypes types, String toFind) {
    if (types.byLabel(toFind).isPresent()) {
      return types.byLabel(toFind).get();
    }

    for (LabelType lt : types.getLabelTypes()) {
      if (toFind.equalsIgnoreCase(lt.getName())) {
        return lt;
      }
    }
    return null;
  }
}
