// 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.forcedraft;

import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Argument;

import com.google.gerrit.extensions.annotations.CapabilityScope;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.sshd.CommandMetaData;
import com.google.gerrit.sshd.SshCommand;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

@RequiresCapability(value = GlobalCapability.ADMINISTRATE_SERVER, scope = CapabilityScope.CORE)
@CommandMetaData(name = "force-draft", description = "changes patch set to draft")
public class ForceDraft extends SshCommand {

  private static final String CHANGE_SECTION = "change";

  private static final String ALLOW_DRAFT = "allowDrafts";

  /**
   * The PatchSet specified by argument.
   */
  private PatchSet patchSet;

  /**
   * Parent Change for patchSet.
   */
  private Change parentChange;

  @Inject
  private Provider<ReviewDb> dbProvider;

  @Inject
  private @GerritServerConfig Config config;

  @Argument(index = 0, required = true, usage = "<change, patch set> to be changed to draft")
  private void addPatchSetId(final String token) {
    try {
      patchSet = parsePatchSet(token);
      parentChange = getParentChange();
    } catch (UnloggedFailure e) {
      throw new IllegalArgumentException(e.getMessage(), e);
    } catch (OrmException e) {
      throw new IllegalArgumentException("database error", e);
    }
  }

  /**
   * Gets parent Change for patchSet.
   *
   * @return The parent Change
   * @throws OrmException
   */
  private Change getParentChange() throws OrmException {
    Change parentChange =
        dbProvider.get().changes().get(patchSet.getId().getParentKey());
    return parentChange;
  }

  /**
   * Parses a string formatted as <Change id>,<PatchSet number>
   *
   * @param changePatchSet
   * @return The PatchSet specified by change_patchSet string.
   * @throws UnloggedFailure
   * @throws OrmException
   */
  private PatchSet parsePatchSet(String changePatchSet) throws UnloggedFailure,
      OrmException {
    if (changePatchSet.matches("^[1-9][0-9]*,[1-9][0-9]*$")) {
      final PatchSet.Id patchSetId;
      try {
        patchSetId = PatchSet.Id.parse(changePatchSet);
      } catch (IllegalArgumentException e) {
        throw new UnloggedFailure(1, "\"" + changePatchSet
            + "\" is not a valid patch set");
      }
      final PatchSet patchSet = dbProvider.get().patchSets().get(patchSetId);
      if (patchSet == null) {
        throw new UnloggedFailure(1, "\"" + changePatchSet
            + "\" no such patch set");
      }
      return patchSet;
    }
    throw new UnloggedFailure(1, "\"" + changePatchSet
        + "\" is not a valid patch set");
  }

  /**
   * Sends message to stdout with new line.
   *
   * @param message
   */
  private void sendUserInfo(String message) {
    stdout.print(message + "\n");
  }

  /**
   * Gets a string representation of the Change.Status.
   *
   * @param changeStatus
   * @return The name of the Change.Status.
   */
  private String getStatusName(Change.Status changeStatus) {
    String statusName = changeStatus.toString().toLowerCase() + ".";
    return statusName;
  }

  /**
   * Sets PatchSet specified by argument as Draft if parentChange has status
   * NEW.
   *
   * @return The updated PatchSet.
   * @throws OrmException
   */
  private PatchSet setPatchSetAsDraft() throws OrmException {
    final PatchSet updatedPatchSet =
        dbProvider.get().patchSets()
            .atomicUpdate(patchSet.getId(), new AtomicUpdate<PatchSet>() {
              @Override
              public PatchSet update(PatchSet patchset) {
                patchset.setDraft(true);
                sendUserInfo("Patch set successfully set to draft.");
                return patchset;
              }
            });
    return updatedPatchSet;
  }

  /**
   * Returns all PatchSets in Change with Id = changeId.
   *
   * @param changeId
   * @return A Iterable<PatchSet> view of all Patch sets in change.
   * @throws OrmException
   */
  private Iterable<PatchSet> getPatchSetsForChange(Change.Id changeId)
      throws OrmException {
    return dbProvider.get().patchSets().byChange(changeId);
  }

  /**
   * Checks if every PatchSet in Change, with Id = changeId, is drafts.
   *
   * @param changeId
   * @return Returns true if all PatchSets in Change are drafts.
   * @throws OrmException
   */
  private boolean isAllPatchSetsInChangeDrafts(Change.Id changeId)
      throws OrmException {
    boolean isAllDrafts = true;
    Iterable<PatchSet> patchSets = getPatchSetsForChange(changeId);
    for (PatchSet patchset : patchSets) {
      if (!patchset.isDraft()) {
        isAllDrafts = false;
        break;
      }
    }
    return isAllDrafts;
  }

  /**
   * Updates parentChange to draft if every Patch set in Change is Draft.
   *
   * @return
   * @throws OrmException
   */
  private Change updateChange() throws OrmException {
    final Change updatedChange =
        dbProvider.get().changes()
            .atomicUpdate(parentChange.getId(), new AtomicUpdate<Change>() {
              @Override
              public Change update(Change change) {
                boolean shouldBeDraft;
                try {
                  shouldBeDraft =
                      isAllPatchSetsInChangeDrafts(parentChange.getId());
                } catch (OrmException e) {
                  sendUserInfo("Unable to check if every patch set in change is draft.");
                  shouldBeDraft = false;
                }
                if (shouldBeDraft) {
                  change.setStatus(Change.Status.DRAFT);
                  sendUserInfo("Every patch set in change is draft, change set to draft.");
                }
                return change;
              }
            });
    return updatedChange;
  }
  /**
   * Updates PatchSet and, if applicable, parent Change.
   *
   * @throws OrmException
   */
  private void updatePatchSet() throws OrmException {
    Change.Status changeStatus = parentChange.getStatus();
    switch (changeStatus) {
      case NEW:
        setPatchSetAsDraft();
        updateChange();
        break;
      default:
        sendUserInfo("Unable to set patch set as draft, change is "
            + getStatusName(changeStatus));
        break;
    }
  }

  private boolean isDraftWorkFlowDisabled() {
    boolean draftsAllowed =
        config.getBoolean(CHANGE_SECTION, ALLOW_DRAFT, true);
    return !draftsAllowed;
  }

  @Override
  public void run() throws UnloggedFailure, Failure, Exception {
    if (isDraftWorkFlowDisabled()) {
      sendUserInfo("Draft workflow disabled in gerrit.config, unable to set to draft.");
    } else if (patchSet.isDraft()) {
      sendUserInfo("Patch set is already draft.");
    } else {
      updatePatchSet();
    }
  }
}
