#' Generate p-Rep Test-Control Designs: Method II
#'
#' Constructs partially replicated (p-rep) test-control
#' designs for multiple environments using an affine
#' resolvable partially balanced incomplete block design
#' framework. The method accommodates several admissible
#' numbers of environments and introduces one control
#' treatment per environment.
#'
#' @param p An integer (\eqn{p \ge 3}).
#'
#' @return A list of p-rep test-control designs for all
#' admissible values of the number of environments.
#' Each design contains design parameters,
#' non-randomized layouts, and randomized layouts.
#'
#' @export
TCpRep2 <- function(p){

  # Input Validation

  if(p < 3)
    stop("p must be at least 3")

  # Number of Test Lines

  vt <- p * (p - 1)

  # Admissible Values of e

  e.values <- (2:(p - 1))[
    (p - 1) %% (2:(p - 1)) == 0
  ]

  if(length(e.values) == 0)
    stop("No admissible value of e exists")

  all.designs <- list()

  # Replication 1

  R1 <- lapply(
    1:(p - 1),
    function(h)
      ((h - 1) * p + 1):(h * p)
  )

  # Replication 2

  R2 <- lapply(
    1:p,
    function(g)
      seq(g, vt, by = p)
  )

  # Loop over admissible values of e

  for(e in e.values){

    blocks.per.env <- (p - 1) / e

    grp <- split(
      1:(p - 1),
      rep(1:e, each = blocks.per.env)
    )

    environments <- vector("list", e)

    for(i in 1:e){

      env_blocks <- list()

      # R1 blocks

      for(j in grp[[i]]){

        env_blocks[[length(env_blocks) + 1]] <- R1[[j]]

      }

      # Control Treatment

      ctrl <- paste0("C", i)

      # Augmented R2 blocks

      for(j in 1:p){

        env_blocks[[length(env_blocks) + 1]] <-
          c(R2[[j]], ctrl)

      }

      env.mat <- do.call(
        rbind,
        env_blocks
      )

      rownames(env.mat) <- paste0(
        "B",
        1:nrow(env.mat)
      )

      environments[[i]] <- env.mat

    }

    names(environments) <- paste0(
      "Environment_",
      1:e
    )

    # Design

    Design <- environments

    # Parameters

    b <- sum(
      sapply(
        environments,
        nrow
      )
    )

    Parameters <- data.frame(
      Parameter = c(
        "Number of Test Treatments (vt)",
        "Number of Controls (vc)",
        "Number of Environments (e)",
        "Number of Blocks (b)",
        "Test Replication (rt)",
        "Control Replication (rc)",
        "Block Size (k)"
      ),
      Value = c(
        vt,
        e,
        e,
        b,
        3,
        p,
        p
      )
    )

    # Non-Randomized Layout

    NonRandomized_Layout <- lapply(
      environments,
      function(env){

        data.frame(
          Block = rownames(env),
          Lines = apply(
            env,
            1,
            function(x)
              paste(x, collapse = " ")
          ),
          row.names = NULL,
          stringsAsFactors = FALSE
        )

      }
    )

    # Randomized Layout

    Randomized_Design <- lapply(
      environments,
      function(env){

        rnd <- t(
          apply(
            env,
            1,
            sample
          )
        )

        rownames(rnd) <- rownames(env)

        rnd

      }
    )

    Randomized_Layout <- lapply(
      Randomized_Design,
      function(env){

        data.frame(
          Block = rownames(env),
          Lines = apply(
            env,
            1,
            function(x)
              paste(x, collapse = " ")
          ),
          row.names = NULL,
          stringsAsFactors = FALSE
        )

      }
    )

    all.designs[[paste0("E", e)]] <-
      structure(
        list(
          Parameters = Parameters,
          Design = Design,
          NonRandomized_Layout = NonRandomized_Layout,
          Randomized_Layout = Randomized_Layout
        ),
        class = "TCpRep"
      )

  }

  return(
    structure(
      all.designs,
      class = "TCpRep2"
    )
  )
}
#' Print p-Rep Test-Control Design
#'
#' @param x An object of class "TCpRep2".
#' @param ... Further arguments.
#'
#' @return The input object invisibly.
#'
#' @exportS3Method print TCpRep2
print.TCpRep2 <- function(x, ...){

  for(i in names(x)){

    cat("\n========================================\n")
    cat("Design in environments =", sub("E", "", i), "\n")
    cat("========================================\n\n")

    cat("Design Parameters\n\n")

    print(
      x[[i]]$Parameters,
      row.names = FALSE
    )

    cat("\n----------------------------------------\n\n")

    cat("Non-Randomized Layout\n\n")

    for(env in names(x[[i]]$NonRandomized_Layout)){

      cat(
        sub("Environment_", "Environment ", env),
        "\n"
      )

      print(
        x[[i]]$NonRandomized_Layout[[env]],
        row.names = FALSE
      )

      cat("\n")
    }

    cat("----------------------------------------\n\n")

    cat("Randomized Layout\n\n")

    for(env in names(x[[i]]$Randomized_Layout)){

      cat(
        sub("Environment_", "Environment ", env),
        "\n"
      )

      print(
        x[[i]]$Randomized_Layout[[env]],
        row.names = FALSE
      )

      cat("\n")
    }
  }

  invisible(x)
}





