library(R6)

pivot_helper <- function (data, rows = NULL, cols = NULL, value = NULL, wt = NULL, 
    within = NULL, withinfun = NULL, fun = NULL, pivot = NULL, wrap = F) 
{
    # cols_quo <- rlang::enquo(cols)
    # value_quo <- rlang::enquo(value)
    # wt_quo <- rlang::enquo(wt)
    # within_quo <- rlang::enquo(within)
    if (is.null(fun)) {
        fun <- sum
    }
    grouped <- data %>% dplyr::group_by(dplyr::across(c({{cols}}, {{rows}})), .drop = FALSE)
    if (is.null(value)) {
        summarized <- grouped %>% dplyr::mutate(value = 1) %>% 
            dplyr::summarise(value = fun(value))
    }
    else {
      if(is.numeric(value)){
        summarized <- grouped %>% dplyr::summarise(value = fun(value))}else{
          summarized <- grouped %>% dplyr::summarise(value = fun(grouped[value]))
          
        }
    }
    if (is.null(within)) {
        withined <- summarized
    }
    else {
        withined <- summarized %>% dplyr::group_by(dplyr::across(c({
            {
                within
            }
        })), .drop = FALSE)
    }
    arranged <- withined
    ungrouped <- arranged %>% dplyr::ungroup()
    tidy <- ungrouped
    if(is.null(pivot)){pivot <- TRUE}
    if (pivot == F | is.null(cols)) {
        tidy
    }
    else { 
        tidy %>% tidyr::pivot_wider(names_from = {
            {
                cols
            }
        })
    }
}


Tidypivot <- R6Class("Tidypivot",
                       public = list(
                         
                         # objects
                         data = NULL,
                         rows = NULL,
                         cols = NULL,
                         fun = NULL,
                         value = NULL, 
                         wt = NULL, 
                         within = NULL, 
                         withinfun = NULL, 
                         pivot = NULL, 
                         wrap = NULL, 
                         out = NULL,
                       
                         

                         # functions
                         update = function(data = NULL, rows = NULL, cols = NULL, 
                                           fun = NULL, value = NULL, wt = NULL, pivot = NULL){ # a method
                           
                           # updating
                           if(!is.null(data)){self$data <- data}
                           if(!is.null(rows)){self$rows <- rows}
                           if(!is.null(cols)){self$cols <- cols}
                           if(!is.null(fun)){self$fun <- fun}
                           # if(!is.null(wt)){self$wt <- wt}
                           if(!is.null(value)){self$value <- value}
                           if(!is.null(pivot)){self$pivot <- pivot}

                           
                           
                          # displaying
                          self$out <- pivot_helper(data = self$data,
                                                   rows = self$rows,
                                                   cols = self$cols,
                                                   fun = self$fun,
                                                   # wt = self$wt,
                                                   value = self$value,
                                                   pivot = self$pivot
                                         
                                                              )
                           
                           invisible(self)          #returns
                           
                                     },
                         
                         print = function() {  # print method; default is to print everything

                           # str(self)
                           print(self$out)

                         }
                       )
)
library(tidytitanic)
library(magrittr)
tidy_titanic %>% 
  tidypivot::pivot_helper(cols = sex, pivot = F)
## # A tibble: 2 × 2
##   sex    value
##   <fct>  <dbl>
## 1 Male    1731
## 2 Female   470
flat_titanic %>% 
  tidypivot::pivot_helper(cols = sex, value = freq, fun = sum, pivot = F)
## # A tibble: 2 × 2
##   sex    value
##   <fct>  <dbl>
## 1 Male    1731
## 2 Female   470
my_tp <- Tidypivot$new() 

my_tp
## NULL
my_tp$update(data = tidy_titanic, cols = "sex")
my_tp$out
## # A tibble: 1 × 2
##    Male Female
##   <dbl>  <dbl>
## 1  1731    470
my_tp$update(rows = "class")
## `summarise()` has grouped output by 'sex'. You can override using the `.groups`
## argument.
my_tp$out
## # A tibble: 4 × 3
##   class  Male Female
##   <fct> <dbl>  <dbl>
## 1 1st     180    145
## 2 2nd     179    106
## 3 3rd     510    196
## 4 Crew    862     23
# wrap and pipe
tp_init <- function(data = NULL, rows = NULL, cols = NULL, fun = NULL,
                    value = NULL, wt = NULL, pivot = NULL
                    ){
  
  my_pivot <- Tidypivot$new()
  
  
  my_pivot$update(data = data, rows = rows, cols = cols, fun = fun, 
                  value = value, wt = wt, pivot = pivot)
  
  my_pivot
  
}

tp_advance <- function(pivot_input, data = NULL, rows = NULL, cols = NULL, fun = NULL,
                       value = NULL, wt = NULL, pivot = NULL){
  
  my_pivot <- pivot_input
  
  my_pivot$update(data = data, rows = rows, cols = cols, fun = fun, 
                  value = value, wt = wt, pivot = pivot)
  
  my_pivot
  
}
tp_init(data = tidy_titanic) ->
pivot0; pivot0
## # A tibble: 1 × 1
##   value
##   <dbl>
## 1  2201
pivot0 %>% 
  tp_advance(cols = "sex") ->
pivot1; pivot1
## # A tibble: 1 × 2
##    Male Female
##   <dbl>  <dbl>
## 1  1731    470
pivot1 %>% 
  tp_advance(rows = "class") ->
pivot2; pivot2
## # A tibble: 4 × 3
##   class  Male Female
##   <fct> <dbl>  <dbl>
## 1 1st     180    145
## 2 2nd     179    106
## 3 3rd     510    196
## 4 Crew    862     23
pivot2 %>% 
  tp_advance(cols = c("sex", "age")) ->
pivot3; pivot3
## # A tibble: 4 × 5
##   class Male_Child Male_Adult Female_Child Female_Adult
##   <fct>      <dbl>      <dbl>        <dbl>        <dbl>
## 1 1st            5        175            1          144
## 2 2nd           11        168           13           93
## 3 3rd           48        462           31          165
## 4 Crew           0        862            0           23
pivot3 %>% 
  tp_advance(pivot = F) ->
pivot4; pivot4
## # A tibble: 16 × 4
##    sex    age   class value
##    <fct>  <fct> <fct> <dbl>
##  1 Male   Child 1st       5
##  2 Male   Child 2nd      11
##  3 Male   Child 3rd      48
##  4 Male   Child Crew      0
##  5 Male   Adult 1st     175
##  6 Male   Adult 2nd     168
##  7 Male   Adult 3rd     462
##  8 Male   Adult Crew    862
##  9 Female Child 1st       1
## 10 Female Child 2nd      13
## 11 Female Child 3rd      31
## 12 Female Child Crew      0
## 13 Female Adult 1st     144
## 14 Female Adult 2nd      93
## 15 Female Adult 3rd     165
## 16 Female Adult Crew     23
tp_init(data = flat_titanic)
## # A tibble: 1 × 1
##   value
##   <dbl>
## 1    32
tp_init(data = flat_titanic) %>%
  tp_advance(cols = "sex") %>% 
  # tp_advance(value = "freq") %>% 
  tp_advance(rows = "class") %>% 
  tp_advance(cols = c("sex", "age")) %>% 
  tp_advance(pivot = F)
## # A tibble: 16 × 4
##    sex    age   class value
##    <fct>  <fct> <fct> <dbl>
##  1 Male   Child 1st       2
##  2 Male   Child 2nd       2
##  3 Male   Child 3rd       2
##  4 Male   Child Crew      2
##  5 Male   Adult 1st       2
##  6 Male   Adult 2nd       2
##  7 Male   Adult 3rd       2
##  8 Male   Adult Crew      2
##  9 Female Child 1st       2
## 10 Female Child 2nd       2
## 11 Female Child 3rd       2
## 12 Female Child Crew      2
## 13 Female Adult 1st       2
## 14 Female Adult 2nd       2
## 15 Female Adult 3rd       2
## 16 Female Adult Crew      2
Tidypivot2 <- R6Class("Tidypivot2",
                       public = list(
                         
                         # objects
                         data = NULL,
                         rows = NULL,
                         cols = NULL,
                         fun = NULL,
                         value = NULL, 
                         wt = NULL, 
                         within = NULL, 
                         withinfun = NULL, 
                         pivot = T, 
                         wrap = F, 
                         
                         out = NULL,
                       
                         

                         # functions
                         update = function(data = NULL, rows = NULL, cols = NULL, 
                                           fun = NULL, value = NULL, wt = NULL){ # a method
                           
                           # updating
                           if(!is.null(data)){self$data <- data}
                           # if(!is.null(rows)){self$rows <- rows}
                           if(!is.null(cols)){self$cols <- cols}
                           # if(!is.null(fun)){self$fun <- fun}
                           # if(!is.null(wt)){self$wt <- wt}
                           # if(!is.null(value)){self$value <- value}

                           
                           
                          # displaying
                          self$out <- tidypivot::pivot_helper(data = self$data,
                                                              # rows = self$rows,
                                                              cols = self$cols#,
                                                              # ,
                                                              # fun = self$fun,
                                                              # wt = self$wt,
                                                              # value = self$value
                                                              )
                           
                           invisible(self)          #returns
                           
                                     },
                         
                         print = function() {  # print method; default is to print everything

                           # str(self)
                           print(self$out)

                         }
                       )
)

```