#' Adjust Zhong's two-stage Phase II design
#' @description Adjust Zhong's two-stage design for over-running or
#'   under-running.
#' @details This function enumerates feasible second-stage boundaries after the
#'   first-stage sample size and boundaries have been fixed.
#' @param n1 Sample size at stage 1.
#' @param r1 Inefficacy boundary at stage 1.
#' @param s1 Efficacy boundary at stage 1. If there is no early stopping for
#'   efficacy, \code{s1} should equal \code{n1}.
#' @param n2 Sample size at stage 2.
#' @param alpha1 Left-side overall type I error.
#' @param alpha2 right-side overall type I error.
#' @param beta Type II error.
#' @param pc A numeric vector of response rates. It should have length 1 or 2.
#' @param pe Alternative hypothesis response rate.
#' @param ... Unused arguments.
#' @return An object of class \code{"opt.design"}, returned as a list
#'   containing:
#'   \item{bdry}{The rejection boundaries.}
#'   \item{error}{The true type I and type II errors.}
#'   \item{n}{The sample size at each stage.}
#'   \item{complete}{The complete list of feasible designs.}
#'   \item{alpha1}{The input left-side type I error.}
#'   \item{alpha2}{The input right-side type I error.}
#'   \item{beta}{The input type II error.}
#'   \item{pc}{The input response-rate vector.}
#'   \item{pe}{The input alternative response rate.}
#'   \item{stage}{The number of stages in the selected design.}
#' @author Wenchuan Guo <wguo1017@gmail.com>, Jianan Hui <jiananhuistat@gmail.com>
#' @import stats
#' @export
#' @examples 
#'  n1 <- 22
#'  r1 <- 6
#'  s1 <- 22
#'  n2 <- 24
#'  pc <- 0.4
#'  pe <- pc + 0.15
#'  alpha1 <- 0.3
#'  alpha2 <- 0.1
#'  beta <- 0.2
#'  out <- adj.two(n1, r1, s1, n2, alpha1, alpha2, beta, pc, pe)


adj.two <- function(n1, r1, s1, n2, alpha1, alpha2, beta, pc, pe, ...){
  if(length(pc) == 1) {
    pc <- rep(pc, 2)
  }
  L1 <- pbinom(r1, n1, pc[1])
  R1 <- 1 - pbinom(s1, n1, pc[2])
  t1 <- (r1+1) : s1
  db_left <- dbinom(t1, n1, pc[1])
  db_right <- dbinom(t1, n1, pc[2])
  db_pe <- dbinom(t1, n1, pe)
  results <- vector("list", max(0, (s1 + n2) - r1))
  idx <- 0L
  for(r2 in (s1 + n2) : (r1+1)){
    L2 <- L1 + sum(db_left * pbinom(r2 - t1, n2, pc[1]))
    if(L2 <= alpha1) {
      s2_l <- ifelse(s1!=n1, max(r2, s1), r2)
      for(s2 in s2_l : (s1+n2)) {
        R2 <- R1 + sum(db_right * (1 - pbinom(s2 - t1, n2, pc[2])))
        if(R2 <= alpha2) {
          Rpe <- sum(db_pe * (1 - pbinom(s2 - t1, n2, pe))) + 1 - pbinom(s1, n1, pe)
          idx <- idx + 1L
          results[[idx]] <- c(L1, L2, R1, R2, 1 - Rpe, r1, r2, s1, s2, n1, n2)
        } 
        else next
      }
    } else next 
  }
  if(idx == 0L) {
    stop("No feasible design found")
  }
  out <- round(do.call(rbind, results[seq_len(idx)]), 4)
  # out <- out[out[, 5] < (beta + 0.2), ]
  out <- out[order(-out[, 2], -out[, 4], out[, 5]), ]
  out <- as.matrix(do.call(rbind, by(out, out[, 7], FUN=function(x) head(x, 1))))
  colnames(out) <- c("alpha11", "alpha12", "alpha21", "alpha22", "beta", "r1", "r2", "s1", "s2", "n1", "n2")
  out <- out[order(-out[, 2], -out[, 4], out[, 5]), ]
  opt <- out[1, ]
  res <- list(bdry = opt[6:9], error = opt[1:5], n = opt[10:11], complete = out)
  input <- list(alpha1 = alpha1, alpha2 = alpha2, beta = beta, pc = pc, pe = pe, stage = 2)
  res <- c(res, input)
  class(res) <- "opt.design"
  return(res)
}
