#' @title Augmented Inverse Probability Weighting (AIPW) uses tmle or tmle3 as inputs
#'
#' @description `AIPW_nuis` class for users to manually input nuisance functions (estimates from the exposure and the outcome models)
#'
#' @details Create an AIPW_nuis object that uses users' input nuisance functions from the exposure model \eqn{P(A| W)},
#'  and the outcome models \eqn{P(Y| do(A=0), W)} and \eqn{P(Y| do(A=1), W.Q)}:
#'      \deqn{
#'      \psi(a) = E{[ I(A=a) / P(A=a|W) ] * [Y-P(Y=1|A,W)] + P(Y=1| do(A=a),W) }
#'      }
#'  Note: If outcome is missing, replace (A=a) with (A=a, observed=1) when estimating the propensity scores.
#'
#' @section Constructor:
#' \code{AIPW$new(Y = NULL, A = NULL, tmle_fit = NULL, verbose = TRUE)}
#'
#' ## Constructor Arguments
#' \tabular{lll}{
#' \strong{Argument}      \tab   \strong{Type}     \tab     \strong{Details} \cr
#' \code{Y}               \tab   Integer           \tab     A vector of outcome (binary (0, 1) or continuous) \cr
#' \code{A}               \tab   Integer           \tab     A vector of binary exposure (0 or 1) \cr
#' \code{mu0}             \tab   Numeric             \tab    User input of \eqn{P(Y=1| do(A = 0),W_Q)} \cr
#' \code{mu1}             \tab   Numeric             \tab    User input of \eqn{P(Y=1| do(A = 1),W_Q)} \cr
#' \code{raw_p_score}     \tab   Numeric             \tab    User input of \eqn{P(A=a|W_g)} \cr
#' \code{verbose}         \tab   Logical           \tab    Whether to print the result (Default = TRUE) \cr
#' \code{stratified_fitted}  \tab   Logical           \tab    Whether mu0 & mu1 was estimated only using `A=0` & `A=1` (Default = FALSE) \cr
#' }
#'
#' @section Public Methods:
#'  \tabular{lll}{
#'  \strong{Methods}      \tab   \strong{Details}                                      \tab \strong{Link}     \cr
#'  \code{summary()}      \tab   Summary of the average treatment effects from AIPW    \tab   [summary.AIPW_base]\cr
#'  \code{plot.p_score()} \tab   Plot the propensity scores by exposure status         \tab   [plot.p_score]\cr
#'  \code{plot.ip_weights()} \tab   Plot the inverse probability weights using truncated propensity scores  \tab   [plot.ip_weights]\cr
#'  }
#'
#' @section Public Variables:
#'  \tabular{lll}{
#'  \strong{Variable}     \tab   \strong{Generated by}      \tab     \strong{Return} \cr
#'  \code{n}              \tab   Constructor                \tab     Number of observations \cr
#'  \code{obs_est}        \tab   Constructor                \tab     Components calculating average causal effects \cr
#'  \code{estimates}      \tab   `summary()`                \tab     A list of Risk difference, risk ratio, odds ratio \cr
#'  \code{result}         \tab   `summary()`                \tab     A matrix contains RD, ATT, ATC, RR and OR with their SE and 95%CI \cr
#'  \code{g.plot}         \tab   `plot.p_score()`           \tab     A density plot of propensity scores by exposure status \cr
#'  \code{ip_weights.plot}         \tab   `plot.ip_weights()`           \tab     A box plot of inverse probability weights \cr
#'  }
#'
#' ## Public Variable Details
#' \describe{
#'    \item{\code{stratified_fit}}{An indicator for whether the outcome model is fitted stratified by exposure status in the`fit()` method.
#'    Only when using `stratified_fit()` to turn on `stratified_fit = TRUE`, `summary` outputs average treatment effects among the treated and the controls.}
#'    \item{\code{obs_est}}{This list includes propensity scores (`p_score`), counterfactual predictions (`mu`, `mu1` & `mu0`) and efficient influence functions (`aipw_eif1` & `aipw_eif0`)}
#'    \item{\code{g.plot}}{This plot is generated by `ggplot2::geom_density`}
#'    \item{\code{ip_weights.plot}}{This plot uses truncated propensity scores stratified by exposure status (`ggplot2::geom_boxplot`)}
#' }
#'
#' @return \code{AIPW_nuis} object
#'
#' @export
AIPW_nuis <- R6::R6Class(
  "AIPW_tmle",
  portable = TRUE,
  inherit = AIPW_base,
  public = list(
    #-------------------------constructor----------------------------#
    initialize = function(Y=NULL, A=NULL, mu0 = NULL , mu1 = NULL, raw_p_score = NULL, verbose=TRUE, stratified_fitted=FALSE){
      #initialize from AIPW_base class
      super$initialize(Y=Y,A=A,verbose=verbose)
      message("Cross-fitting for estimating nuisance functions is recommended for using SuperLearner.")
      self$obs_est$mu0 <- mu0
      self$obs_est$mu1 <- mu1
      self$obs_est$mu <- self$obs_est$mu0*(1-private$A) + self$obs_est$mu1*(private$A)
      self$obs_est$raw_p_score <- raw_p_score
      self$stratified_fitted = stratified_fitted
    }
  )
)
