class RepairRunResource {

  @PUT
  @Path("/{id}/state/{state}")
  public Response modifyRunState(
      @Context UriInfo uriInfo,
      @PathParam("id") UUID repairRunId,
      @PathParam("state") Optional<String> stateStr)
      throws ReaperException {

    LOG.info("modify repair run state called with: id = {}, state = {}", repairRunId, stateStr);
    try {
      if (!stateStr.isPresent()) {
        return createMissingArgumentResponse("state");
      }

      Optional<RepairRun> repairRun = context.storage.getRepairRun(repairRunId);
      if (!repairRun.isPresent()) {
        return Response.status(Status.NOT_FOUND).entity("repair run " + repairRunId + " doesn't exist").build();
      }

      final RepairRun.RunState newState = parseRunState(stateStr.get());
      final RunState oldState = repairRun.get().getRunState();
      if (oldState == newState) {
        String msg = "given \"state\" " + stateStr + " is same as the current run state";
        return Response.noContent().entity(msg).location(buildRepairRunUri(uriInfo, repairRun.get())).build();
      }
      if ((isStarting(oldState, newState) || isResuming(oldState, newState) || isRetrying(oldState, newState))
          && isUnitAlreadyRepairing(repairRun.get())) {

        String errMsg = "repair unit already has run " + repairRun.get().getRepairUnitId() + " in RUNNING state";
        LOG.error(errMsg);
        return Response.status(Status.CONFLICT).entity(errMsg).build();
      }

      if (isStarting(oldState, newState)) {
        return startRun(uriInfo, repairRun.get());
      } else if (isPausing(oldState, newState)) {
        return pauseRun(uriInfo, repairRun.get());
      } else if (isResuming(oldState, newState) || isRetrying(oldState, newState)) {
        return resumeRun(uriInfo, repairRun.get());
      } else if (isAborting(oldState, newState)) {
        return abortRun(uriInfo, repairRun.get());
      } else {
        String errMsg = String.format("Transition %s->%s not supported.", oldState.toString(), newState.toString());
        LOG.error(errMsg);
        return Response.status(Status.CONFLICT).entity(errMsg).build();
      }
    } catch (ValidationException ex) {
      return Response.status(Status.BAD_REQUEST).entity(ex.getMessage()).build();
    }
  }

  public  RepairRunResource(AppContext context);

}