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

import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.rules.RulesCache;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.TestSubmitRule.Input;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.kohsuke.args4j.Option;

import java.util.List;
import java.util.Map;

public class TestSubmitRule implements RestModifyView<RevisionResource, Input> {
  public enum Filters {
    RUN, SKIP
  }

  public static class Input {
    @DefaultInput
    public String rule;
    public Filters filters;
  }

  private final Provider<ReviewDb> db;
  private final ChangeData.Factory changeDataFactory;
  private final RulesCache rules;
  private final AccountLoader.Factory accountInfoFactory;

  @Option(name = "--filters", usage = "impact of filters in parent projects")
  private Filters filters = Filters.RUN;

  @Inject
  TestSubmitRule(Provider<ReviewDb> db,
      ChangeData.Factory changeDataFactory,
      RulesCache rules,
      AccountLoader.Factory infoFactory) {
    this.db = db;
    this.changeDataFactory = changeDataFactory;
    this.rules = rules;
    this.accountInfoFactory = infoFactory;
  }

  @Override
  public List<Record> apply(RevisionResource rsrc, Input input)
      throws AuthException, BadRequestException, OrmException {
    if (input == null) {
      input = new Input();
    }
    if (input.rule != null && !rules.isProjectRulesEnabled()) {
      throw new AuthException("project rules are disabled");
    }
    input.filters = MoreObjects.firstNonNull(input.filters, filters);
    SubmitRuleEvaluator evaluator = new SubmitRuleEvaluator(
        changeDataFactory.create(db.get(), rsrc.getControl()));

    List<SubmitRecord> records = evaluator.setPatchSet(rsrc.getPatchSet())
          .setLogErrors(false)
          .setSkipSubmitFilters(input.filters == Filters.SKIP)
          .setRule(input.rule)
          .canSubmit();
    List<Record> out = Lists.newArrayListWithCapacity(records.size());
    AccountLoader accounts = accountInfoFactory.create(true);
    for (SubmitRecord r : records) {
      out.add(new Record(r, accounts));
    }
    if (!out.isEmpty()) {
      out.get(0).prologReductionCount = evaluator.getReductionsConsumed();
    }
    accounts.fill();
    return out;
  }

  static class Record {
    SubmitRecord.Status status;
    String errorMessage;
    Map<String, AccountInfo> ok;
    Map<String, AccountInfo> reject;
    Map<String, None> need;
    Map<String, AccountInfo> may;
    Map<String, None> impossible;
    Integer prologReductionCount;

    Record(SubmitRecord r, AccountLoader accounts) {
      this.status = r.status;
      this.errorMessage = r.errorMessage;

      if (r.labels != null) {
        for (SubmitRecord.Label n : r.labels) {
          AccountInfo who = n.appliedBy != null
              ? accounts.get(n.appliedBy)
              : new AccountInfo(null);
          label(n, who);
        }
      }
    }

    private void label(SubmitRecord.Label n, AccountInfo who) {
      switch (n.status) {
        case OK:
          if (ok == null) {
            ok = Maps.newLinkedHashMap();
          }
          ok.put(n.label, who);
          break;
        case REJECT:
          if (reject == null) {
            reject = Maps.newLinkedHashMap();
          }
          reject.put(n.label, who);
          break;
        case NEED:
          if (need == null) {
            need = Maps.newLinkedHashMap();
          }
          need.put(n.label, new None());
          break;
        case MAY:
          if (may == null) {
            may = Maps.newLinkedHashMap();
          }
          may.put(n.label, who);
          break;
        case IMPOSSIBLE:
          if (impossible == null) {
            impossible = Maps.newLinkedHashMap();
          }
          impossible.put(n.label, new None());
          break;
      }
    }
  }

  static class None {
  }
}
