print.distfreereg <-
  function(x, ..., digits = 3, col_sep = 2, show_params = TRUE){
    stopifnot(is(x, "distfreereg"), is.numeric(digits), is.numeric(col_sep),
              isTRUE(show_params) || isFALSE(show_params))
    
    stopifnot(!is.null(x[["observed_stats"]]), !is.null(names(x[["observed_stats"]])),
              !is.null(x[["p"]][["value"]]), !is.null(x[["data"]][["Y"]]),
              !is.null(x[["theoretical_stats"]][[1]]))
    
    if(is.null(x[["theta_hat"]])){
      show_params <- FALSE
    }
    
    # Parameter_estimates
    if(isTRUE(show_params)){
      parameters <- sprintf(paste0("%1.", digits, "e"), x[["theta_hat"]])
      names(parameters) <- names(x[["theta_hat"]])
    }
    
    # Stats
    B <- length(x[["theoretical_stats"]][[1]])
    j <- length(names(x[["observed_stats"]]))
    col_names <- c("Stat", "Value", "Pr(>Value)", "MCSE")
    stat_matrix <- matrix(NA_character_, nrow = 1 + j, ncol = 4)
    stat_matrix[1,] <- col_names
    for(i in seq_len(j)){
      if(identical(x[["p"]][["value"]][[i]], 0)){
        prepend <- "<"
        x[["p"]][["value"]][[i]] <- 1/B
      } else {
        if(identical(x[["p"]][["value"]][[i]], 1)){
          prepend <- ">"
          x[["p"]][["value"]][[i]] <- 1-1/B
        } else {
          prepend <- ""
        }
      }
      stat_matrix[i+1, 1] <- names(x[["observed_stats"]])[i]
      stat_matrix[i+1, 2:4] <- sprintf(paste0("%1.", digits, "e"),
                                       c(x[["observed_stats"]][[i]],
                                         x[["p"]][["value"]][[i]],
                                         x[["p"]][["mcse"]][[i]]))
      stat_matrix[i+1, 3] <- paste0(prepend, stat_matrix[i+1, 3])
    }
    
    buffered_stat_matrix <- buffer_matrix(stat_matrix)
    
    # Output
    cat("Number of observations:", length(x[["fitted_values"]]))
    cat("\nLength of EPSP:", length(x[["epsp"]]), "\n")
    cat("Monte Carlo simulations:", B, "\n")
    if(isTRUE(show_params)){
      cat("\nEstimated parameter values:\n")
      print.default(parameters, quote = FALSE, digits = digits)
    }
    cat("\nObserved statistics:\n")
    for(i in seq_len(nrow(stat_matrix)))
      cat(paste(buffered_stat_matrix[i,],
                collapse = paste0(rep(" ", times = col_sep), collapse = "")), "\n")
    cat("---\n`MCSE' is the Monte Carlo standard error of the estimated p-value.\n\n")
  }
