// 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.googlesource.gerrit.plugins.wip;

import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.server.change.ChangesCollection;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.git.UpdateException;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.project.ProjectControl;
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.google.inject.Provider;

import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

@CommandMetaData(name = "set", description = "Mark the change as WIP or Ready")
class SetCommand extends SshCommand {
  private static final Logger log = LoggerFactory.getLogger(SetCommand.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 review")
  void addPatchSetId(String token) {
    try {
      PatchSet ps = psParser.parsePatchSet(token, projectControl, branch);
      patchSets.add(ps);
    } catch (UnloggedFailure e) {
      throw new IllegalArgumentException(e.getMessage(), e);
    } catch (OrmException e) {
      throw new IllegalArgumentException("database error", e);
    }
  }

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

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

  @Option(name = "--message", aliases = "-m",
      usage = "cover message on change(s)", metaVar = "MESSAGE")
  private String changeComment;

  @Option(name = "--wip", aliases = "-w",
      usage = "mark the specified change(s) as WIP")
  private boolean wipChange;

  @Option(name = "--readyChange", aliases = "-r",
      usage = "mark the specified change(s) as Ready for Review")
  private boolean readyChange;

  @Inject
  private Provider<WorkInProgress> wipProvider;

  @Inject
  private Provider<ReadyForReview> readyProvider;

  @Inject
  ChangeIndexer indexer;

  @Inject
  ChangesCollection changes;

  @Inject
  PatchSetParser psParser;

  @Override
  protected void run() throws UnloggedFailure {
    if (wipChange && readyChange) {
      throw error("wip and ready options are mutually exclusive");
    }
    if (!wipChange && !readyChange) {
      throw error("wip or ready option must be specified");
    }

    boolean ok = true;
    for (PatchSet patchSet : patchSets) {
      try {
        mark(patchSet);
      } catch (RestApiException | IOException
          | OrmException | UpdateException e) {
        ok = false;
        writeError("fatal: internal server error while approving "
            + patchSet.getId() + "\n");
        log.error("internal error while approving " + patchSet.getId(), e);
      }
    }

    if (!ok) {
      throw new UnloggedFailure(1, "one or more mark operations failed");
    }
  }

  private void mark(PatchSet patchSet) throws ResourceConflictException,
      OrmException, IOException, RestApiException, UpdateException {
    RevisionResource rsrc =
        new RevisionResource(changes.parse(patchSet.getId().getParentKey()),
            patchSet);
    BaseAction.Input input = new BaseAction.Input();
    input.message = changeComment;
    if (wipChange) {
      wipProvider.get().apply(rsrc, input);
    } else {
      readyProvider.get().apply(rsrc, input);
    }
  }

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

  private static UnloggedFailure error(String msg) {
    return new UnloggedFailure(1, msg);
  }
}
