// 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 static com.google.common.base.Preconditions.checkArgument;

import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.Maps;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.restapi.change.ChangesCollection;
import com.google.gerrit.server.restapi.change.Revisions;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gerrit.sshd.commands.PatchSetParser;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.verifystatus.common.VerificationInfo;
import com.googlesource.gerrit.plugins.verifystatus.common.VerifyInput;
import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@RequiresCapability(value = SaveReportCapability.ID, fallBackToAdmin = false)
@CommandMetaData(name = "save", description = "Save patchset verification data")
public class SaveCommand extends SshCommand {
  private static final Logger log = LoggerFactory.getLogger(SaveCommand.class);

  private final Set<PatchSet> patchSets = new HashSet<>();

  @Argument(
      index = 0,
      required = true,
      multiValued = true,
      metaVar = "{COMMIT | CHANGE,PATCHSET}",
      usage = "list of commits or patch sets to verify")
  void addPatchSetId(String token) {
    try {
      PatchSet ps = psParser.parsePatchSet(token, projectState, branch);
      patchSets.add(ps);
    } catch (UnloggedFailure e) {
      throw new IllegalArgumentException(e.getMessage(), e);
    } catch (StorageException e) {
      throw new IllegalArgumentException("database error", e);
    }
  }

  @Option(
      name = "--project",
      aliases = "-p",
      usage = "project containing the specified patch set(s)")
  private ProjectState projectState;

  @Option(name = "--branch", aliases = "-b", usage = "branch containing the specified patch set(s)")
  private String branch;

  @Option(
      name = "--verification",
      aliases = "-v",
      usage = "verification to set the result for",
      metaVar = "VERIFY=OUTCOME")
  void addJob(String token) {
    parseWithEquals(token);
  }

  private void parseWithEquals(String text) {
    log.debug("processing verification: " + text);
    checkArgument(!Strings.isNullOrEmpty(text), "Empty verification data");
    Map<String, String> params = null;
    try {
      params = Splitter.on("|").withKeyValueSeparator("=").split(text);
    } catch (IllegalArgumentException e) {
      throw new IllegalArgumentException(String.valueOf("Invalid verification parameters"));
    }

    String name = params.get("name");
    checkArgument(name != null, "Verification is missing a name");
    checkArgument(!name.isEmpty(), "Verification is missing a name");
    String value = params.get("value");
    checkArgument(value != null, "Verification is missing a value");
    checkArgument(!value.isEmpty(), "Verification is missing a value");
    String abstain = params.get("abstain");
    String rerun = params.get("rerun");
    VerificationInfo data = new VerificationInfo();
    data.name = name;
    data.value = Short.parseShort(value);
    data.abstain = Boolean.valueOf(abstain);
    data.rerun = Boolean.valueOf(rerun);
    data.url = params.get("url");
    data.reporter = params.get("reporter");
    data.comment = params.get("comment");
    data.category = params.get("category");
    data.duration = params.get("duration");
    jobResult.put(name, data);
  }

  @Inject private PostVerification postVerification;

  @Inject private PatchSetParser psParser;

  @Inject private Revisions revisions;

  @Inject private ChangesCollection changes;

  private Map<String, VerificationInfo> jobResult = Maps.newHashMap();

  @Override
  protected void run() throws UnloggedFailure {
    boolean ok = true;

    for (PatchSet patchSet : patchSets) {
      try {
        verifyOne(patchSet);
      } catch (UnloggedFailure e) {
        ok = false;
        writeError("error: " + e.getMessage() + "\n");
      }
    }

    if (!ok) {
      throw new UnloggedFailure(1, "one or more verifications failed;" + " review output above");
    }
  }

  private void applyVerification(PatchSet patchSet, VerifyInput verify)
      throws RestApiException, OrmException, IOException, PermissionBackendException {
    RevisionResource revResource =
        revisions.parse(
            changes.parse(patchSet.id().changeId()), IdString.fromUrl(patchSet.id().getId()));
    postVerification.apply(revResource, verify);
  }

  private void verifyOne(PatchSet patchSet) throws UnloggedFailure {
    VerifyInput verify = new VerifyInput();
    verify.verifications = jobResult;
    try {
      applyVerification(patchSet, verify);
    } catch (RestApiException | OrmException | IOException | PermissionBackendException e) {
      throw PatchSetParser.error(e.getMessage());
    }
  }

  private void writeError(String msg) {
    try {
      err.write(msg.getBytes(ENC));
    } catch (IOException e) {
    }
  }
}
