// Copyright (C) 2015 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.googlesource.gerrit.plugins.verifystatus;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.common.errors.PermissionDeniedException;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.CapabilityControl;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.googlesource.gerrit.plugins.verifystatus.common.VerificationInfo;
import com.googlesource.gerrit.plugins.verifystatus.common.VerifyInput;
import com.googlesource.gerrit.plugins.verifystatus.server.CiDb;
import com.googlesource.gerrit.plugins.verifystatus.server.PatchSetVerification;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
@RequiresCapability(SaveReportCapability.ID)
public class PostVerification implements RestModifyView<RevisionResource, VerifyInput> {
  private static final Logger log = LoggerFactory.getLogger(PostVerification.class);
  private final SchemaFactory<CiDb> schemaFactory;
  private final String pluginName;
  private final Provider<CurrentUser> userProvider;

  @Inject
  PostVerification(
      @PluginName String pluginName,
      Provider<CurrentUser> userProvider,
      SchemaFactory<CiDb> schemaFactory) {
    this.pluginName = pluginName;
    this.userProvider = userProvider;
    this.schemaFactory = schemaFactory;
  }

  @Override
  public Response<?> apply(RevisionResource revision, VerifyInput input)
      throws AuthException, BadRequestException, UnprocessableEntityException, OrmException,
          IOException {

    try {
      checkPermission();
    } catch (PermissionDeniedException err) {
      throw new BadRequestException("fatal: " + err.getMessage());
    }

    if (input.verifications == null) {
      throw new BadRequestException("Missing verifications field");
    }

    try (CiDb db = schemaFactory.open()) {
      // Only needed for Google Megastore (that we don't use yet)
      db.patchSetVerifications().beginTransaction(null);
      boolean dirty = false;
      try {
        dirty |= updateLabels(revision, db, input.verifications);
        if (dirty) {
          db.commit();
        }
      } finally {
        db.rollback();
      }
    }
    return Response.none();
  }

  private boolean updateLabels(
      RevisionResource resource, CiDb db, Map<String, VerificationInfo> jobs)
      throws OrmException, BadRequestException {
    Preconditions.checkNotNull(jobs);

    List<PatchSetVerification> ups = Lists.newArrayList();
    Map<String, PatchSetVerification> current = scanLabels(resource, db);

    Timestamp ts = TimeUtil.nowTs();
    for (Map.Entry<String, VerificationInfo> ent : jobs.entrySet()) {
      String name = ent.getKey();
      if (name == null) {
        throw new BadRequestException("Missing name field");
      }
      PatchSetVerification c = current.remove(name);
      Short value = ent.getValue().value;
      if (value == null) {
        throw new BadRequestException("Missing value field");
      }
      if (c != null) {
        // update a result
        c.setGranted(ts);
        c.setValue(value);
        if (Boolean.TRUE.equals(ent.getValue().abstain)) {
          c.setAbstain(true);
        }
        if (Boolean.TRUE.equals(ent.getValue().rerun)) {
          c.setRerun(true);
        }
        String url = ent.getValue().url;
        if (url != null) {
          c.setUrl(url);
        }
        String job_name = c.getName();
        if (job_name != null) {
          c.setName(job_name);
        }
        String reporter = ent.getValue().reporter;
        if (reporter != null) {
          c.setReporter(reporter);
        }
        String comment = ent.getValue().comment;
        if (comment != null) {
          c.setComment(comment);
        }
        String category = ent.getValue().category;
        if (category != null) {
          c.setCategory(category);
        }
        String duration = ent.getValue().duration;
        if (duration != null) {
          c.setDuration(duration);
        }
        log.info("Updating job " + c.getJob() + " for change " + c.getPatchSetId());
        ups.add(c);
      } else {
        // add new result
        String job_id = UUID.randomUUID().toString();
        c =
            new PatchSetVerification(
                new PatchSetVerification.Key(resource.getPatchSet().getId(), new LabelId(job_id)),
                value,
                ts);
        c.setAbstain(ent.getValue().abstain);
        c.setRerun(ent.getValue().rerun);
        c.setUrl(ent.getValue().url);
        c.setName(name);
        c.setReporter(ent.getValue().reporter);
        c.setComment(ent.getValue().comment);
        c.setCategory(ent.getValue().category);
        c.setDuration(ent.getValue().duration);
        log.info("Adding job " + c.getJob() + " for change " + c.getPatchSetId());
        ups.add(c);
      }
    }

    db.patchSetVerifications().upsert(ups);
    return !ups.isEmpty();
  }

  private Map<String, PatchSetVerification> scanLabels(RevisionResource resource, CiDb db)
      throws OrmException {
    Map<String, PatchSetVerification> current = Maps.newHashMap();
    for (PatchSetVerification v :
        db.patchSetVerifications().byPatchSet(resource.getPatchSet().getId())) {
      current.put(v.getJobId().get(), v);
    }
    return current;
  }

  /**
   * Assert that the current user is permitted to perform saving of verification reports.
   *
   * <p>As the @RequireCapability guards at various entry points of internal commands implicitly add
   * administrators (which we want to avoid), we also check permissions within QueryShell and grant
   * access only to those who canPerformRawQuery, regardless of whether they are administrators or
   * not.
   *
   * @throws PermissionDeniedException
   */
  private void checkPermission() throws PermissionDeniedException {
    CapabilityControl ctl = userProvider.get().getCapabilities();
    if (!ctl.canPerform(SaveReportCapability.getName(pluginName))) {
      throw new PermissionDeniedException(
          String.format(
              "%s does not have \"%s\" capability.",
              userProvider.get().getUserName(), new SaveReportCapability().getDescription()));
    }
  }
}
