// Copyright (C) 2010 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.Lists;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.OrPredicate;
import com.google.gerrit.server.query.Predicate;
import com.google.gerrit.server.util.LabelVote;
import com.google.inject.Provider;

import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LabelPredicate extends OrPredicate<ChangeData> {
  private static final int MAX_LABEL_VALUE = 4;

  static class Args {
    final ProjectCache projectCache;
    final ChangeControl.GenericFactory ccFactory;
    final IdentifiedUser.GenericFactory userFactory;
    final Provider<ReviewDb> dbProvider;
    final String value;
    final Set<Account.Id> accounts;
    final AccountGroup.UUID group;

    private Args(
        ProjectCache projectCache,
        ChangeControl.GenericFactory ccFactory,
        IdentifiedUser.GenericFactory userFactory,
        Provider<ReviewDb> dbProvider,
        String value,
        Set<Account.Id> accounts,
        AccountGroup.UUID group) {
      this.projectCache = projectCache;
      this.ccFactory = ccFactory;
      this.userFactory = userFactory;
      this.dbProvider = dbProvider;
      this.value = value;
      this.accounts = accounts;
      this.group = group;
    }
  }

  private static class Parsed {
    private final String label;
    private final String test;
    private final int expVal;

    private Parsed(String label, String test, int expVal) {
      this.label = label;
      this.test = test;
      this.expVal = expVal;
    }
  }

  private final String value;

  LabelPredicate(ProjectCache projectCache,
      ChangeControl.GenericFactory ccFactory,
      IdentifiedUser.GenericFactory userFactory, Provider<ReviewDb> dbProvider,
      String value, Set<Account.Id> accounts, AccountGroup.UUID group) {
    super(predicates(new Args(projectCache, ccFactory, userFactory, dbProvider,
        value, accounts, group)));
    this.value = value;
  }

  private static List<Predicate<ChangeData>> predicates(Args args) {
    String v = args.value;
    Parsed parsed = null;

    try {
      LabelVote lv = LabelVote.parse(v);
      parsed = new Parsed(lv.getLabel(), "=", lv.getValue());
    } catch (IllegalArgumentException e) {
      // Try next format.
    }

    try {
      LabelVote lv = LabelVote.parseWithEquals(v);
      parsed = new Parsed(lv.getLabel(), "=", lv.getValue());
    } catch (IllegalArgumentException e) {
      // Try next format.
    }

    if (parsed == null) {
      Matcher m = Pattern.compile("(>|>=|=|<|<=)([+-]?\\d+)$").matcher(v);
      if (m.find()) {
        parsed = new Parsed(v.substring(0, m.start()), m.group(1),
            value(m.group(2)));
      } else {
        parsed = new Parsed(v, "=", 1);
      }
    }

    int min, max;
    switch (parsed.test) {
      case "=":
      default:
        min = max = parsed.expVal;
        break;
      case ">":
        min = parsed.expVal + 1;
        max = MAX_LABEL_VALUE;
        break;
      case ">=":
        min = parsed.expVal;
        max = MAX_LABEL_VALUE;
        break;
      case "<":
        min = -MAX_LABEL_VALUE;
        max = parsed.expVal - 1;
        break;
      case "<=":
        min = -MAX_LABEL_VALUE;
        max = parsed.expVal;
        break;
    }
    List<Predicate<ChangeData>> r =
        Lists.newArrayListWithCapacity(max - min + 1);
    for (int i = min; i <= max; i++) {
      r.add(onePredicate(args, parsed.label, i));
    }
    return r;
  }

  private static Predicate<ChangeData> onePredicate(Args args, String label,
      int expVal) {
    if (expVal != 0) {
      return equalsLabelPredicate(args, label, expVal);
    } else {
      return noLabelQuery(args, label);
    }
  }

  private static int value(String value) {
    if (value.startsWith("+")) {
      value = value.substring(1);
    }
    return Integer.parseInt(value);
  }

  private static Predicate<ChangeData> noLabelQuery(Args args, String label) {
    List<Predicate<ChangeData>> r =
        Lists.newArrayListWithCapacity(2 * MAX_LABEL_VALUE);
    for (int i = 1; i <= MAX_LABEL_VALUE; i++) {
      r.add(not(equalsLabelPredicate(args, label, i)));
      r.add(not(equalsLabelPredicate(args, label, -i)));
    }
    return and(r);
  }

  private static Predicate<ChangeData> equalsLabelPredicate(Args args,
      String label, int expVal) {
    if (args.accounts == null || args.accounts.isEmpty()) {
      return new EqualsLabelPredicate(args, label, expVal, null);
    } else {
      List<Predicate<ChangeData>> r = Lists.newArrayList();
      for (Account.Id a : args.accounts) {
        r.add(new EqualsLabelPredicate(args, label, expVal, a));
      }
      return or(r);
    }
  }

  @Override
  public String toString() {
    return ChangeQueryBuilder.FIELD_LABEL + ":" + value;
  }
}
