#' ################################################################################
# This function takes as input the days of symptoms onset of individual cases
#' and provides back the control days using a monthly time stratified
#' case-crossover design addittionally matching on the day of the week
################################################################################

#' @title tssc_sampling
#'
#' @description This function takes as imput the days of symptoms onset of individual cases
#' and provides back the control days using a monthly time stratified
#' case-crossover design matched on DoW
#'
#' @param data A dataframe to use
#' @param dates The name of the variable containing dates of
#' the case onset (e.g. "dates")
#'
#' @return A list of sampling control days for each case in the dataset
#' @export
#'
#' @examples tscc_sampling(data, "day_of_symptoms")
#' @examples tscc_sampling(data, "dates_of_events")
#'
#' @author Giovenale Moirano

tscc_sampling <- function(data, dates) {

  # Create an empty matrix and populate it with potential sampling date around
  # the case day. 
  
  m1 <- as.data.frame(matrix(rep(NA, nrow(data) * 61),
                             nrow = nrow(data), ncol = 61, byrow = T
  ))
  
  if (class(data[[dates]]) != "Date" & class(data[[dates]]) != "character") {
    stop("variable 'dates' must be provided as character or date format and expressed as '%Y-%m-%d'")
  } else if (class(data[[dates]]) == "Date") {
    for (i in 1:nrow(data)) {
      m1[i, ] <- as.character(as.Date((data[[dates]][i] - 30):(data[[dates]][i] + 30),
        origin = "1970-01-01"
      ))
    }
  } else if (class(data[[dates]]) == "character") {
    for (i in 1:nrow(data)) {
      m1[i, ] <- as.character(as.Date((as.Date(data[[dates]][i], format = "%Y-%m-%d") - 30):(as.Date(data[[dates]][i], format = "%Y-%m-%d") + 30),
        origin = "1970-01-01"
      ))
    }
  }
  
  # transform date to date each element of the matrix 
  for (i in 1:ncol(m1)) {
    m1[, i] <- as.Date(m1[, i], format = "%Y-%m-%d")
  }

  # create a matrix with month of candidate sampling dates
  
  mon <- as.data.frame(matrix(rep(NA, nrow(data) * 61),
    nrow = nrow(data), ncol = 61, byrow = T
  ))
  
  for (i in 1:ncol(m1)) {
    mon[, i] <- as.character(month(m1[, i]))
  }

  # Set condition 1: Month must be the same of case day
  cond1 <- NULL
  val <- NULL
  for (i in 1:nrow(mon)) {
    val <- mon[i, 31]
    cond1[[i]] <- mon[i, ] == val
  }

  # create a matrix with day of the week of candidate sampling dates
  
  dow <- as.data.frame(matrix(rep(NA, nrow(data) * 61),
    nrow = nrow(data), ncol = 61, byrow = T
  ))

  for (i in 1:ncol(m1)) {
    dow[, i] <- as.character(wday(m1[, i], week_start = 1))
  }
  
  # Set condition 2: Day of the week must be the same of case day
  
  cond2 <- NULL
  val <- NULL
  for (i in 1:nrow(dow)) {
    val <- dow[i, 31]
    cond2[[i]] <- dow[i, ] == val
  }

  cond1 <- unlist(cond1)
  cond1_m <- matrix(cond1, nrow = nrow(m1), byrow = TRUE)
  cond1_m

  cond2 <- unlist(cond2)
  cond2_m <- matrix(cond2, nrow = nrow(m1), byrow = TRUE)
  cond2_m

  # Select days that meet the two conditions
  
  output <- NULL
  va1l <- NULL
  val2 <- NULL
  for (i in 1:nrow(m1)) {
    val1 <- cond1_m[i, ]
    val2 <- cond2_m[i, ]
    output[[i]] <- m1[i, val1 == TRUE & val2 == TRUE]
  }

  # Raframe format and variables names 
  
  names(output) <- paste0("ID", 1:length(output))
  output2 <- stack(unlist(output))
  output2$ind
  output2$ID <- ifelse(substr(
    output2$ind, nchar(as.character(output2$ind)) - 3,
    nchar(as.character(output2$ind)) - 3
  ) == ".",
  substr(output2$ind, 1, nchar(as.character(output2$ind)) - 4),
  substr(output2$ind, 1, nchar(as.character(output2$ind)) - 3)
  )

  output2$index_date <- substr(output2$ind, nchar(as.character(output2$ind)) - 2, nchar(as.character(output2$ind)))
  output2$caco <- 0
  output2$caco[output2$index_date == "V31"] <- 1
  output2$sampling_date <- as.Date(output2$values, format = "%Y-%m-%d", origin = "1970-01-01")
  return(output2[, c("ID", "caco", "sampling_date")])
  
}
