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

import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.extensions.common.AccountInfo;
import com.google.gerrit.extensions.common.TestSubmitRuleInput;
import com.google.gerrit.extensions.common.TestSubmitRuleInput.Filters;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.project.SubmitRuleEvaluator;
import com.google.gerrit.server.project.SubmitRuleOptions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.RulesCache;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.kohsuke.args4j.Option;

public class TestSubmitRule implements RestModifyView<RevisionResource, TestSubmitRuleInput> {
  private final Provider<ReviewDb> db;
  private final ChangeData.Factory changeDataFactory;
  private final RulesCache rules;
  private final AccountLoader.Factory accountInfoFactory;
  private final SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory;

  @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,
      SubmitRuleEvaluator.Factory submitRuleEvaluatorFactory) {
    this.db = db;
    this.changeDataFactory = changeDataFactory;
    this.rules = rules;
    this.accountInfoFactory = infoFactory;
    this.submitRuleEvaluatorFactory = submitRuleEvaluatorFactory;
  }

  @Override
  public List<Record> apply(RevisionResource rsrc, TestSubmitRuleInput input)
      throws AuthException, OrmException {
    if (input == null) {
      input = new TestSubmitRuleInput();
    }
    if (input.rule != null && !rules.isProjectRulesEnabled()) {
      throw new AuthException("project rules are disabled");
    }
    input.filters = MoreObjects.firstNonNull(input.filters, filters);

    SubmitRuleOptions opts =
        SubmitRuleOptions.builder()
            .skipFilters(input.filters == Filters.SKIP)
            .rule(input.rule)
            .logErrors(false)
            .build();

    ChangeData cd = changeDataFactory.create(db.get(), rsrc.getNotes());
    List<SubmitRecord> records = submitRuleEvaluatorFactory.create(opts).evaluate(cd);

    List<Record> out = Lists.newArrayListWithCapacity(records.size());
    AccountLoader accounts = accountInfoFactory.create(true);
    for (SubmitRecord r : records) {
      out.add(new Record(r, accounts));
    }
    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;

    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 = new LinkedHashMap<>();
          }
          ok.put(n.label, who);
          break;
        case REJECT:
          if (reject == null) {
            reject = new LinkedHashMap<>();
          }
          reject.put(n.label, who);
          break;
        case NEED:
          if (need == null) {
            need = new LinkedHashMap<>();
          }
          need.put(n.label, new None());
          break;
        case MAY:
          if (may == null) {
            may = new LinkedHashMap<>();
          }
          may.put(n.label, who);
          break;
        case IMPOSSIBLE:
          if (impossible == null) {
            impossible = new LinkedHashMap<>();
          }
          impossible.put(n.label, new None());
          break;
      }
    }
  }

  static class None {}
}
