// 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.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, 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)
          .evaluate();
    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;
    Long 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 {
  }
}
