require(tidyverse)
vect_name_region <- c('ARA', 'BFC', 'BRE', 'CVL', 'COR', 'GES', 'HDF', 'IDF', 'NAQ', 'NOR', 'OCC', 'PAC', 'PDL')

### Functions used to generate the vaccination schedule based on hypotheses regarding
### the delay between doses, the vaccine roll-out pace, and the number of doses being delivered every month.

### The script is suited to generate matrices for the following age-groups:
### 0-9 ; 10-17 ; 18-29 ; 30-39 ; 40-44 ; 45-49 ; 50-54 ; 55-59 ; 60-64 ; 65-69 ; 70-74 ; 75-79 ; 80+
age_groups_to_target <- c('0-17y', '18-49y', '50-64y', '65-74y', '75y+')
corresponding_ages <- c(rep(1, 2),
                        rep(2, 4),
                        rep(3, 3),
                        rep(4, 2),
                        rep(5, 2))

vaccine_priority_Age <- list(list(list('75y+', 0:3)),
                             list(list('65-74y', 0:3)),
                             list(list('50-64y', 0:3)),
                             list(list('18-49y', 0:3)))

vaccine_priority_Age_From6574 <- list(list(list('65-74y', 0:3)),
                                      list(list('50-64y', 0:3)),
                                      list(list('18-49y', 0:3)))

vaccine_priority_Age_From5064 <- list(list(list('50-64y', 0:3)),
                                      list(list('18-49y', 0:3)))

vaccine_priority_Age_Just50p <- list(list(list('75y+', 0:3)),
                                     list(list('65-74y', 0:3)),
                                     list(list('50-64y', 0:3)))


### Functions used assuming no change in the roll-out pace
get_nbFirstDosesPerDay_nVaccines <- function(df_Doses,
                                             seq_n_maxDosesPerDay,
                                             date_beginning_vaccine = as.Date('2021-02-01'),
                                             date_end_vaccine = as.Date('2021-12-31'),
                                             seq_DelayBetweenDoses){
  
  # df_Doses is a dataframe with the following columns:
  ### DateDelivery : the date at which vaccines doses will be delivered
  ### Doses_i : the number of doses of vaccine i for by date of delivery
  
  seq_Dates <- seq.Date(from = date_beginning_vaccine,
                        to = date_end_vaccine,
                        by = 'day')
  
  nVaccines <- length(seq_n_maxDosesPerDay)
  
  list_seq_FirstDoses <- lapply(1:nVaccines, FUN = function(iVaccine){
    rep(0, length(seq_Dates))
  })
  list_seq_SecondDoses <- lapply(1:nVaccines, FUN = function(iVaccine){
    rep(0, length(seq_Dates) + seq_DelayBetweenDoses[iVaccine])
  })
  
  list_seq_DosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
    sapply(seq_Dates, FUN = function(tmp_date){
      DosesAlreadyDistributed <- sum(df_Doses[df_Doses$DateDelivery <= tmp_date, paste0('Doses_', iVaccine)])
    })
  })  # Vector where you store the available doses on a given day (remove second doses)
 
  list_seq_DosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
    c(list_seq_DosesAvailable[[iVaccine]], rep(1e8, seq_DelayBetweenDoses[iVaccine]))
  })
  
  
  for(i in 1:length(seq_Dates)){
    tmp_date <- seq_Dates[i]
    list_tmpSecondDosesToDistribute <- lapply(1:nVaccines, FUN = function(iVaccine){
      list_seq_SecondDoses[[iVaccine]][i]
    })
    ## Get a number of doses that can be distributed (and checking that there will be enough)
    list_tmpDosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
      tmp_seqDosesAvailable <- list_seq_DosesAvailable[[iVaccine]]
      min(tmp_seqDosesAvailable[i:length(tmp_seqDosesAvailable)])
    })
    list_tmpSecondDosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
      tmp_seqDosesAvailable <- list_seq_DosesAvailable[[iVaccine]]
      min(tmp_seqDosesAvailable[(i + seq_DelayBetweenDoses[iVaccine]):length(tmp_seqDosesAvailable)]/2)
    })
    list_tmpDosesThatCanBeDistributed <- lapply(1:nVaccines, FUN = function(iVaccine){
      seq_n_maxDosesPerDay[iVaccine] - list_tmpSecondDosesToDistribute[[iVaccine]]
    })
    list_tmp_FirstDosesToDistribute <- lapply(1:nVaccines, FUN = function(iVaccine){
      min(list_tmpDosesAvailable[[iVaccine]],
          list_tmpSecondDosesAvailable[[iVaccine]],
          list_tmpDosesThatCanBeDistributed[[iVaccine]])
    })
    for(iVaccine in 1:nVaccines){
      if(seq_DelayBetweenDoses[iVaccine] == 0){ # Single-dose vaccine
        list_seq_FirstDoses[[iVaccine]][[i]] <- list_tmp_FirstDosesToDistribute[[iVaccine]]
        
        list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] <- 
          list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] - 
          list_tmp_FirstDosesToDistribute[[iVaccine]]
        
        
      } else{
        list_seq_FirstDoses[[iVaccine]][[i]] <- list_tmp_FirstDosesToDistribute[[iVaccine]]
        list_seq_SecondDoses[[iVaccine]][i + seq_DelayBetweenDoses[iVaccine]] <- list_tmp_FirstDosesToDistribute[[iVaccine]]
        
        list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] <- 
          list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] - 
          list_tmp_FirstDosesToDistribute[[iVaccine]]
        list_seq_DosesAvailable[[iVaccine]][(i + seq_DelayBetweenDoses[iVaccine]):(length(list_seq_DosesAvailable[[iVaccine]]))] <- 
          list_seq_DosesAvailable[[iVaccine]][(i + seq_DelayBetweenDoses[iVaccine]):(length(list_seq_DosesAvailable[[iVaccine]]))] - 
          list_tmp_FirstDosesToDistribute[[iVaccine]]
      }
      
    }
  }
  
  list_schema <- list(seq_Dates = seq_Dates,
                      list_seq_FirstDoses = list_seq_FirstDoses,
                      list_seq_SecondDoses = list_seq_SecondDoses,
                      list_seq_DosesAvailable = list_seq_DosesAvailable)
                    
  return(list_schema)
}

get_Mat_VaccineStrategy_nVaccines_withComorbidities <- function(date_beginning_vaccine,
                                                                date_end_vaccine,
                                                                vect_maxVC,
                                                                seq_n_maxDosesPerDay,
                                                                df_Doses,
                                                                seq_DelayBetweenDoses,
                                                                list_vaccine_priority,
                                                                N_0, N_1, N_2, N_3){
  ## Defining the matrix
  time_beginning_vaccine <- as.numeric(date_beginning_vaccine)
  time_end_vaccine <- as.numeric(date_end_vaccine)
  
  nVaccines <- length(seq_n_maxDosesPerDay)
  n.ageG <- length(vect_maxVC)
  
  
  list_FirstDoses <- get_nbFirstDosesPerDay_nVaccines(df_Doses,
                                                      seq_n_maxDosesPerDay, 
                                                      date_beginning_vaccine, date_end_vaccine,
                                                      seq_DelayBetweenDoses)
  
  list_vect_nMaxVaccinePerDay <- list_FirstDoses[["list_seq_FirstDoses"]]
  
  list_Mat_VaccineStrategy <- lapply(1:nVaccines, FUN = function(iVaccine){
    Mat_VaccineStrategy <- matrix(0, nrow = time_end_vaccine - time_beginning_vaccine + 1,
                                  ncol = 4*n.ageG)
    
  })
  ## Maximum number of individuals that can be vaccinated in the different age-comorbidities groups
  max_IndivToVaccinate <- c(N_0*vect_maxVC, N_1*vect_maxVC, N_2*vect_maxVC, N_3*vect_maxVC)
  
  list_nGroupsToVaccine <- lapply(1:nVaccines, FUN = function(iVaccine){
    length(list_vaccine_priority[[iVaccine]])
  })
  list_ColumnIndicesMat_VaccineStrategy <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_vaccine_priority[[iVaccine]], FUN = function(l1){
      sort(Reduce('c', lapply(l1, FUN = function(l){
        tmp_comorbidities <- l[[2]]
        tmp_age <- which(age_groups_to_target ==  l[1])
        tmp_indices_age <- which(corresponding_ages == tmp_age)
        Reduce('c',lapply(tmp_comorbidities, FUN = function(tmp_comorbidity){
          tmp_indices_age + (tmp_comorbidity)*n.ageG
        }))
      })))
    })
  })
  list_RepartitionVaccineWithinGroups <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]], FUN = function(tmp_indices){
      tmp_num <- max_IndivToVaccinate[tmp_indices]
      tmp_den <- sum(max_IndivToVaccinate[tmp_indices])
      if(tmp_den == 0){
        tmp_num
      } else{
        tmp_num/tmp_den
      }
    })
  })
  list_MaxIndivToVaccinateWithinGroups <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]], FUN = function(tmp_indices){
      max_IndivToVaccinate[tmp_indices]
    })
  })
  seq_N.AllocatedVaccines <- rep(0, nVaccines)
  seq_nVaccinePerDay <- sapply(1:nVaccines, FUN = function(iVaccine){
    list_vect_nMaxVaccinePerDay[[iVaccine]][1]
  })
  
  t <- 1
  seq_index_groupToVaccinate <- sapply(1:nVaccines, FUN = function(iVaccine){
    1
  })
  
  
  seq_runvacc <- sapply(1:nVaccines, FUN = function(iVaccine){
    TRUE
  })# Boolean storing whether you finished or not the vaccination of the given group on the given day
  seq_change <- rep(T, nVaccines)
  
  
  while(((t <= nrow(list_Mat_VaccineStrategy[[1]])) &
         (sum(seq_runvacc) >=1)
  )){
    ## Number of doses already allocated to the age group we consider
    if(t == 1){
      list_nDosesAlreadyAllocated_All_PerVacc <- lapply(1:nVaccines, FUN = function(iVaccine){
        list_Mat_VaccineStrategy[[iVaccine]][t, ]
      })
      
    } else{
      list_nDosesAlreadyAllocated_All_PerVacc <- lapply(1:nVaccines, FUN = function(iVaccine){
        apply(list_Mat_VaccineStrategy[[iVaccine]][1:t, ], 2, sum)
      })
      
    }
    nDosesAlreadyAllocated_All <- Reduce('+', list_nDosesAlreadyAllocated_All_PerVacc)
    
    
    for(iVaccine in 1:nVaccines){
      tmp_run_vacc <- seq_runvacc[iVaccine]
      if(tmp_run_vacc){
        ## Number of doses to distribute
        tmp_nDosesToAllocate <- seq_nVaccinePerDay[iVaccine]
        ## Repartition of the doses to allocate
        tmp_index_groupToVaccinate <- seq_index_groupToVaccinate[iVaccine]
        tmp_Current_RepartitionAllocation <- list_RepartitionVaccineWithinGroups[[iVaccine]][[tmp_index_groupToVaccinate]]
        tmp_Current_MaxIndivToVaccinate <- list_MaxIndivToVaccinateWithinGroups[[iVaccine]][[tmp_index_groupToVaccinate]]
        
        tmp_nDosesAlreadyAllocated <- nDosesAlreadyAllocated_All[(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]])[[tmp_index_groupToVaccinate]]]
        
        tmp_nDosesToAllocateThisGroupThisDay <- ifelse(tmp_Current_MaxIndivToVaccinate - tmp_nDosesAlreadyAllocated - tmp_nDosesToAllocate*tmp_Current_RepartitionAllocation < 0,
                                                       tmp_Current_MaxIndivToVaccinate - tmp_nDosesAlreadyAllocated,
                                                       tmp_nDosesToAllocate*tmp_Current_RepartitionAllocation)
        list_Mat_VaccineStrategy[[iVaccine]][t, list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] <- 
          list_Mat_VaccineStrategy[[iVaccine]][t, list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] +
          tmp_nDosesToAllocateThisGroupThisDay
        
        seq_N.AllocatedVaccines[iVaccine] <- seq_N.AllocatedVaccines[iVaccine] + sum(tmp_nDosesToAllocateThisGroupThisDay)
        
        nDosesAlreadyAllocated_All[list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] <-  
          nDosesAlreadyAllocated_All[list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] +
          tmp_nDosesToAllocateThisGroupThisDay
        
        
        if(abs(sum(tmp_nDosesToAllocateThisGroupThisDay) -  seq_nVaccinePerDay[iVaccine]) < 1e-8){
          seq_nVaccinePerDay[iVaccine] <- list_vect_nMaxVaccinePerDay[[iVaccine]][t + 1]
          seq_change[iVaccine] <- F
        } else{
          seq_nVaccinePerDay[iVaccine] <- seq_nVaccinePerDay[iVaccine] - sum(tmp_nDosesToAllocateThisGroupThisDay)
          seq_index_groupToVaccinate[iVaccine] <- tmp_index_groupToVaccinate + 1
          seq_change[iVaccine] <- T
        }
      }
    }
    if(sum(seq_change) == 0){
      t <- t + 1
    }
    seq_runvacc <- sapply(1:nVaccines, FUN = function(iVaccine){
      (seq_change[iVaccine] || sum(seq_change) == 0)& # Do you need to run it for another iteration if t did not increase
        (t <= (time_end_vaccine - time_beginning_vaccine + 1) & # Are you by the end of the simulation ?
           (seq_index_groupToVaccinate[iVaccine] <= list_nGroupsToVaccine[[iVaccine]]))  # Is there more groups to vaccinate
    })
    
  }
  
  list_Mat <- list_Mat_VaccineStrategy
  names(list_Mat) <- paste0('Mat_VaccineStrategy_', 1:nVaccines)
  return(list_Mat)
}

get_Mat_VaccineStrategy_nVaccines_justAge <- function(date_beginning_vaccine,
                                                      date_end_vaccine,
                                                      vect_maxVC,
                                                      seq_n_maxDosesPerDay,
                                                      df_Doses,
                                                      seq_DelayBetweenDoses,
                                                      list_vaccine_priority,
                                                      popSize.ageG){
  
  n.ageG <- length(popSize.ageG)
  N_0 <- popSize.ageG
  N_1 <- N_2 <- N_3 <- rep(0, n.ageG)
  
  list_Mat <- get_Mat_VaccineStrategy_nVaccines_withComorbidities(date_beginning_vaccine,
                                                                  date_end_vaccine,
                                                                  vect_maxVC,
                                                                  seq_n_maxDosesPerDay,
                                                                  df_Doses,
                                                                  seq_DelayBetweenDoses,
                                                                  list_vaccine_priority,
                                                                  N_0, N_1, N_2, N_3)
  
  list_Mat_AgeOnly <- lapply(list_Mat, FUN = function(tmp_Mat){
    sapply(1:n.ageG, FUN = function(tmp_age){
      round(tmp_Mat[, tmp_age] + tmp_Mat[, tmp_age + n.ageG] +
              tmp_Mat[, tmp_age + 2*n.ageG] + tmp_Mat[, tmp_age + 3*n.ageG],
            4)
    })
  })
  
  
  return(list_Mat_AgeOnly)
}


get_Mat_Rates_nVaccines_justAge <- function(date_beginning_vaccine,
                                            date_end_vaccine,
                                            vect_maxVC,
                                            seq_n_maxDosesPerDay,
                                            df_Doses,
                                            seq_DelayBetweenDoses,
                                            list_vaccine_priority,
                                            popSize.ageG){
  
  n.ageG <- length(popSize.ageG)
  
  list_Mat_AgeOnly <- get_Mat_VaccineStrategy_nVaccines_justAge(date_beginning_vaccine,
                                                                date_end_vaccine,
                                                                vect_maxVC,
                                                                seq_n_maxDosesPerDay,
                                                                df_Doses,
                                                                seq_DelayBetweenDoses,
                                                                list_vaccine_priority,
                                                                popSize.ageG)
  
  nVaccines <- length(list_Mat_AgeOnly)
  nDays <- nrow(list_Mat_AgeOnly$Mat_VaccineStrategy_1)
  
  
  
  list_Mat_Rates <- lapply(1:nVaccines, FUN = function(i){
    matrix(0, ncol = n.ageG, nrow = nDays)
  })
  names(list_Mat_Rates) <- names(list_Mat_AgeOnly)
  nNonVaccinated.ageG <- popSize.ageG
  for(iDay in 1:nDays){
    list_VectToVaccinate <- lapply(list_Mat_AgeOnly, FUN = function(l){
      l[iDay,]
    })
    list_Vectrates <- lapply(list_VectToVaccinate, FUN = function(l){
      nNewNonVaccinated.ageG <- nNonVaccinated.ageG - l
      log(nNonVaccinated.ageG) - log(nNewNonVaccinated.ageG)
    })
    ## Update the number of non vaccinated individuals in the different age groups
    nNonVaccinated.ageG <- nNonVaccinated.ageG - Reduce('+', list_VectToVaccinate)
    ## Update the list with the rates
    for(iVaccine in 1:nVaccines){
      list_Mat_Rates[[paste0('Mat_VaccineStrategy_', iVaccine)]][iDay, ] <- list_Vectrates[[paste0('Mat_VaccineStrategy_', iVaccine)]] 
    }
  }
  return(list_Mat_Rates)
}



### Functions used when using a change in the roll-out pace for the different vaccines
get_nbFirstDosesPerDay_nVaccines_ChancePace <- function(df_Doses,
                                                        seq_n_maxDosesPerDay_Before,
                                                        seq_n_maxDosesPerDay_After,
                                                        date_beginning_vaccine = as.Date('2021-02-01'),
                                                        date_end_vaccine = as.Date('2021-12-31'),
                                                        seq_DelayBetweenDoses,
                                                        seq_DateChangePace
                                                        ){
  
  # df_Doses is a dataframe with the following columns:
  ### DateDelivery : the date at which vaccines doses will be delivered
  ### Doses_i : the number of doses of vaccine i for by date of delivery
  
  seq_Dates <- seq.Date(from = date_beginning_vaccine,
                        to = date_end_vaccine,
                        by = 'day')
  
  nVaccines <- length(seq_n_maxDosesPerDay_Before)
  
  list_seq_FirstDoses <- lapply(1:nVaccines, FUN = function(iVaccine){
    rep(0, length(seq_Dates))
  })
  list_seq_SecondDoses <- lapply(1:nVaccines, FUN = function(iVaccine){
    rep(0, length(seq_Dates) + seq_DelayBetweenDoses[iVaccine])
  })
  
  list_seq_DosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
    sapply(seq_Dates, FUN = function(tmp_date){
      DosesAlreadyDistributed <- sum(df_Doses[df_Doses$DateDelivery <= tmp_date, paste0('Doses_', iVaccine)])
    })
  })  # Vector where you store the available doses on a given day (remove second doses)
  
  list_seq_DosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
    c(list_seq_DosesAvailable[[iVaccine]], rep(1e8, seq_DelayBetweenDoses[iVaccine]))
  })
  list_vect_n_maxDosesPerDay <- lapply(1:nVaccines, FUN = function(iVaccine){
    tmp_date_change <- seq_DateChangePace[iVaccine]
    tmp_nDoses_Before <- seq_n_maxDosesPerDay_Before[iVaccine]
    tmp_nDoses_After <- seq_n_maxDosesPerDay_After[iVaccine]
    
    ifelse(seq_Dates < tmp_date_change, tmp_nDoses_Before, tmp_nDoses_After)
  })
  
  
  for(i in 1:length(seq_Dates)){
    seq_n_maxDosesPerDay <- sapply(1:nVaccines, FUN = function(iVaccine){
      list_vect_n_maxDosesPerDay[[iVaccine]][i]
    })
    tmp_date <- seq_Dates[i]
    list_tmpSecondDosesToDistribute <- lapply(1:nVaccines, FUN = function(iVaccine){
      list_seq_SecondDoses[[iVaccine]][i]
    })
    ## Get a number of doses that can be distributed (and checking that there will be enough)
    list_tmpDosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
      tmp_seqDosesAvailable <- list_seq_DosesAvailable[[iVaccine]]
      min(tmp_seqDosesAvailable[i:length(tmp_seqDosesAvailable)])
    })
    list_tmpSecondDosesAvailable <- lapply(1:nVaccines, FUN = function(iVaccine){
      tmp_seqDosesAvailable <- list_seq_DosesAvailable[[iVaccine]]
      min(tmp_seqDosesAvailable[(i + seq_DelayBetweenDoses[iVaccine]):length(tmp_seqDosesAvailable)]/2)
    })
    list_tmpDosesThatCanBeDistributed <- lapply(1:nVaccines, FUN = function(iVaccine){
      seq_n_maxDosesPerDay[iVaccine] - list_tmpSecondDosesToDistribute[[iVaccine]]
    })
    list_tmp_FirstDosesToDistribute <- lapply(1:nVaccines, FUN = function(iVaccine){
      min(list_tmpDosesAvailable[[iVaccine]],
          list_tmpSecondDosesAvailable[[iVaccine]],
          list_tmpDosesThatCanBeDistributed[[iVaccine]])
    })
    for(iVaccine in 1:nVaccines){
      list_seq_FirstDoses[[iVaccine]][[i]] <- list_tmp_FirstDosesToDistribute[[iVaccine]]
      list_seq_SecondDoses[[iVaccine]][i + seq_DelayBetweenDoses[iVaccine]] <- list_tmp_FirstDosesToDistribute[[iVaccine]]
      
      list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] <- 
        list_seq_DosesAvailable[[iVaccine]][i:length(list_seq_DosesAvailable[[iVaccine]])] - 
        list_tmp_FirstDosesToDistribute[[iVaccine]]
      list_seq_DosesAvailable[[iVaccine]][(i + seq_DelayBetweenDoses[iVaccine]):(length(list_seq_DosesAvailable[[iVaccine]]))] <- 
        list_seq_DosesAvailable[[iVaccine]][(i + seq_DelayBetweenDoses[iVaccine]):(length(list_seq_DosesAvailable[[iVaccine]]))] - 
        list_tmp_FirstDosesToDistribute[[iVaccine]]
    }
  }
  
  list_schema <- list(seq_Dates = seq_Dates,
                      list_seq_FirstDoses = list_seq_FirstDoses,
                      list_seq_SecondDoses = list_seq_SecondDoses,
                      list_seq_DosesAvailable = list_seq_DosesAvailable)
  
  return(list_schema)
}

get_Mat_VaccineStrategy_nVaccines_withComorbidities_ChangePace <- function(date_beginning_vaccine,
                                                                          date_end_vaccine,
                                                                          vect_maxVC,
                                                                          seq_n_maxDosesPerDay_Before,
                                                                          seq_n_maxDosesPerDay_After,
                                                                          df_Doses,
                                                                          seq_DelayBetweenDoses,
                                                                          seq_DateChangePace,
                                                                          list_vaccine_priority,
                                                                          N_0, N_1, N_2, N_3){
  ## Defining the matrix
  time_beginning_vaccine <- as.numeric(date_beginning_vaccine)
  time_end_vaccine <- as.numeric(date_end_vaccine)
  
  nVaccines <- length(seq_n_maxDosesPerDay_Before)
  n.ageG <- length(vect_maxVC)
  
  list_FirstDoses <- get_nbFirstDosesPerDay_nVaccines_ChancePace(df_Doses,
                                                                 seq_n_maxDosesPerDay_Before,
                                                                 seq_n_maxDosesPerDay_After,
                                                                 date_beginning_vaccine, date_end_vaccine,
                                                                 seq_DelayBetweenDoses,
                                                                 seq_DateChangePace)
  
  list_vect_nMaxVaccinePerDay <- list_FirstDoses[["list_seq_FirstDoses"]]
  
  list_Mat_VaccineStrategy <- lapply(1:nVaccines, FUN = function(iVaccine){
    Mat_VaccineStrategy <- matrix(0, nrow = time_end_vaccine - time_beginning_vaccine + 1,
                                  ncol = 4*n.ageG)
    
  })
  ## Maximum number of individuals that can be vaccinated in the different age-comorbidities groups
  max_IndivToVaccinate <- c(N_0*vect_maxVC, N_1*vect_maxVC, N_2*vect_maxVC, N_3*vect_maxVC)
  
  list_nGroupsToVaccine <- lapply(1:nVaccines, FUN = function(iVaccine){
    length(list_vaccine_priority[[iVaccine]])
  })
  list_ColumnIndicesMat_VaccineStrategy <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_vaccine_priority[[iVaccine]], FUN = function(l1){
      sort(Reduce('c', lapply(l1, FUN = function(l){
        tmp_comorbidities <- l[[2]]
        tmp_age <- which(age_groups_to_target ==  l[1])
        tmp_indices_age <- which(corresponding_ages == tmp_age)
        Reduce('c',lapply(tmp_comorbidities, FUN = function(tmp_comorbidity){
          tmp_indices_age + (tmp_comorbidity)*n.ageG
        }))
      })))
    })
  })
  list_RepartitionVaccineWithinGroups <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]], FUN = function(tmp_indices){
      tmp_num <- max_IndivToVaccinate[tmp_indices]
      tmp_den <- sum(max_IndivToVaccinate[tmp_indices])
      if(tmp_den == 0){
        tmp_num
      } else{
        tmp_num/tmp_den
      }
    })
  })
  list_MaxIndivToVaccinateWithinGroups <- lapply(1:nVaccines, FUN = function(iVaccine){
    lapply(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]], FUN = function(tmp_indices){
      max_IndivToVaccinate[tmp_indices]
    })
  })
  seq_N.AllocatedVaccines <- rep(0, nVaccines)
  seq_nVaccinePerDay <- sapply(1:nVaccines, FUN = function(iVaccine){
    list_vect_nMaxVaccinePerDay[[iVaccine]][1]
  })
  
  t <- 1
  seq_index_groupToVaccinate <- sapply(1:nVaccines, FUN = function(iVaccine){
    1
  })
  
  
  seq_runvacc <- sapply(1:nVaccines, FUN = function(iVaccine){
    TRUE
  })# Boolean storing whether you finished or not the vaccination of the given group on the given day
  seq_change <- rep(T, nVaccines)
  
  
  while(((t <= nrow(list_Mat_VaccineStrategy[[1]])) &
         (sum(seq_runvacc) >=1)
  )){
    ## Number of doses already allocated to the age group we consider
    if(t == 1){
      list_nDosesAlreadyAllocated_All_PerVacc <- lapply(1:nVaccines, FUN = function(iVaccine){
        list_Mat_VaccineStrategy[[iVaccine]][t, ]
      })
      
    } else{
      list_nDosesAlreadyAllocated_All_PerVacc <- lapply(1:nVaccines, FUN = function(iVaccine){
        apply(list_Mat_VaccineStrategy[[iVaccine]][1:t, ], 2, sum)
      })
      
    }
    nDosesAlreadyAllocated_All <- Reduce('+', list_nDosesAlreadyAllocated_All_PerVacc)
    
    
    for(iVaccine in 1:nVaccines){
      tmp_run_vacc <- seq_runvacc[iVaccine]
      if(tmp_run_vacc){
        ## Number of doses to distribute
        tmp_nDosesToAllocate <- seq_nVaccinePerDay[iVaccine]
        ## Repartition of the doses to allocate
        tmp_index_groupToVaccinate <- seq_index_groupToVaccinate[iVaccine]
        tmp_Current_RepartitionAllocation <- list_RepartitionVaccineWithinGroups[[iVaccine]][[tmp_index_groupToVaccinate]]
        tmp_Current_MaxIndivToVaccinate <- list_MaxIndivToVaccinateWithinGroups[[iVaccine]][[tmp_index_groupToVaccinate]]
        
        tmp_nDosesAlreadyAllocated <- nDosesAlreadyAllocated_All[(list_ColumnIndicesMat_VaccineStrategy[[iVaccine]])[[tmp_index_groupToVaccinate]]]
        
        tmp_nDosesToAllocateThisGroupThisDay <- ifelse(tmp_Current_MaxIndivToVaccinate - tmp_nDosesAlreadyAllocated - tmp_nDosesToAllocate*tmp_Current_RepartitionAllocation < 0,
                                                       tmp_Current_MaxIndivToVaccinate - tmp_nDosesAlreadyAllocated,
                                                       tmp_nDosesToAllocate*tmp_Current_RepartitionAllocation)
        list_Mat_VaccineStrategy[[iVaccine]][t, list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] <- 
          list_Mat_VaccineStrategy[[iVaccine]][t, list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] +
          tmp_nDosesToAllocateThisGroupThisDay
        
        seq_N.AllocatedVaccines[iVaccine] <- seq_N.AllocatedVaccines[iVaccine] + sum(tmp_nDosesToAllocateThisGroupThisDay)
        
        nDosesAlreadyAllocated_All[list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] <-  
          nDosesAlreadyAllocated_All[list_ColumnIndicesMat_VaccineStrategy[[iVaccine]][[tmp_index_groupToVaccinate]]] +
          tmp_nDosesToAllocateThisGroupThisDay
        
        
        if(abs(sum(tmp_nDosesToAllocateThisGroupThisDay) -  seq_nVaccinePerDay[iVaccine]) < 1e-8){
          seq_nVaccinePerDay[iVaccine] <- list_vect_nMaxVaccinePerDay[[iVaccine]][t + 1]
          seq_change[iVaccine] <- F
        } else{
          seq_nVaccinePerDay[iVaccine] <- seq_nVaccinePerDay[iVaccine] - sum(tmp_nDosesToAllocateThisGroupThisDay)
          seq_index_groupToVaccinate[iVaccine] <- tmp_index_groupToVaccinate + 1
          seq_change[iVaccine] <- T
        }
      }
    }
    seq_SimulationOver <- sapply(1:nVaccines, FUN = function(iVaccine){
      (seq_index_groupToVaccinate[iVaccine] > list_nGroupsToVaccine[[iVaccine]])
    }) 
    
    if(sum(seq_change[! seq_SimulationOver]) == 0){
      t <- t + 1
    }
    seq_runvacc <- sapply(1:nVaccines, FUN = function(iVaccine){
      (seq_change[iVaccine] || sum(seq_change[! seq_SimulationOver]) == 0) & # Do you need to run it for another iteration if t did not increase
        (t <= (time_end_vaccine - time_beginning_vaccine + 1) & # Are you by the end of the simulation ?
           (seq_index_groupToVaccinate[iVaccine] <= list_nGroupsToVaccine[[iVaccine]]))  # Is there more groups to vaccinate
    })
    
  }
  
  list_Mat <- list_Mat_VaccineStrategy
  names(list_Mat) <- paste0('Mat_VaccineStrategy_', 1:nVaccines)
  return(list_Mat)
}

get_Mat_VaccineStrategy_nVaccines_justAge_ChangePace <- function(date_beginning_vaccine,
                                                                 date_end_vaccine,
                                                                 vect_maxVC,
                                                                 seq_n_maxDosesPerDay_Before,
                                                                 seq_n_maxDosesPerDay_After,
                                                                 df_Doses,
                                                                 seq_DelayBetweenDoses,
                                                                 seq_DateChangePace,
                                                                 list_vaccine_priority,
                                                                 popSize.ageG){
  
  n.ageG <- length(popSize.ageG)
  N_0 <- popSize.ageG
  N_1 <- N_2 <- N_3 <- rep(0, n.ageG)
  
  list_Mat <- get_Mat_VaccineStrategy_nVaccines_withComorbidities_ChangePace(date_beginning_vaccine,
                                                                             date_end_vaccine,
                                                                             vect_maxVC,
                                                                             seq_n_maxDosesPerDay_Before,
                                                                             seq_n_maxDosesPerDay_After,
                                                                             df_Doses,
                                                                             seq_DelayBetweenDoses,
                                                                             seq_DateChangePace,
                                                                             list_vaccine_priority,
                                                                             N_0, N_1, N_2, N_3)
  
  list_Mat_AgeOnly <- lapply(list_Mat, FUN = function(tmp_Mat){
    sapply(1:n.ageG, FUN = function(tmp_age){
      round(tmp_Mat[, tmp_age] + tmp_Mat[, tmp_age + n.ageG] +
              tmp_Mat[, tmp_age + 2*n.ageG] + tmp_Mat[, tmp_age + 3*n.ageG],
            4)
    })
  })
  
  
  return(list_Mat_AgeOnly)
}

get_Mat_Rates_nVaccines_justAge_ChangePace <- function(date_beginning_vaccine,
                                                       date_end_vaccine,
                                                       vect_maxVC,
                                                       seq_n_maxDosesPerDay_Before,
                                                       seq_n_maxDosesPerDay_After,
                                                       df_Doses,
                                                       seq_DelayBetweenDoses,
                                                       seq_DateChangePace,
                                                       list_vaccine_priority,
                                                       popSize.ageG){
  
  n.ageG <- length(popSize.ageG)
  
  list_Mat_AgeOnly <- get_Mat_VaccineStrategy_nVaccines_justAge_ChangePace(date_beginning_vaccine,
                                                                           date_end_vaccine,
                                                                           vect_maxVC,
                                                                           seq_n_maxDosesPerDay_Before,
                                                                           seq_n_maxDosesPerDay_After,
                                                                           df_Doses,
                                                                           seq_DelayBetweenDoses,
                                                                           seq_DateChangePace,
                                                                           list_vaccine_priority,
                                                                           popSize.ageG)
  
  nVaccines <- length(list_Mat_AgeOnly)
  nDays <- nrow(list_Mat_AgeOnly$Mat_VaccineStrategy_1)
  
  
  
  list_Mat_Rates <- lapply(1:nVaccines, FUN = function(i){
    matrix(0, ncol = n.ageG, nrow = nDays)
  })
  names(list_Mat_Rates) <- names(list_Mat_AgeOnly)
  nNonVaccinated.ageG <- popSize.ageG
  for(iDay in 1:nDays){
    list_VectToVaccinate <- lapply(list_Mat_AgeOnly, FUN = function(l){
      l[iDay,]
    })
    list_Vectrates <- lapply(list_VectToVaccinate, FUN = function(l){
      nNewNonVaccinated.ageG <- nNonVaccinated.ageG - l
      log(nNonVaccinated.ageG) - log(nNewNonVaccinated.ageG)
    })
    ## Update the number of non vaccinated individuals in the different age groups
    nNonVaccinated.ageG <- nNonVaccinated.ageG - Reduce('+', list_VectToVaccinate)
    ## Update the list with the rates
    for(iVaccine in 1:nVaccines){
      list_Mat_Rates[[paste0('Mat_VaccineStrategy_', iVaccine)]][iDay, ] <- list_Vectrates[[paste0('Mat_VaccineStrategy_', iVaccine)]] 
    }
  }
  return(list_Mat_Rates)
}




################## Scripts to get the real vaccination schedule
get_Retrospective_Mat_VaccinationStrategy <- function(my_region_name){
  
  ## Loading the VACSI data
  date_file_VACSI <- as.Date('2021-04-17')
  df_VACSI <- read.csv2(paste0('Data/VACSI/', format(date_file_VACSI, '%Y%m%d'), '/vacsi-a-reg-', date_file_VACSI, '-19h10.csv'))
  
  df_VACSI$jour <- as.Date(df_VACSI$jour)
  INSEE_codes <- read.csv2('Data/population_data/INSEE_Code_RegionNames.csv')
  df_VACSI$region_name <- sapply(df_VACSI$reg, FUN = function(tmp_reg){
    tmp_x <- INSEE_codes[INSEE_codes$insee_code == tmp_reg, 'region_name']
  })
  
  
  
  if(my_region_name == 'Metro'){
    
    tmp_df <- df_VACSI %>% filter(region_name %in% vect_name_region, clage_vacsi !=0) %>%
      group_by(jour, clage_vacsi) %>%
      summarise(n_dose1_sum = sum(n_dose1)) %>%
      select(jour, n_dose1_sum, clage_vacsi) %>%
      ungroup() %>% group_by(clage_vacsi) %>%
      select(jour, n_dose1_sum) %>%
      group_split() %>%
      reduce(left_join, by = 'jour')
    
    
  } else{
    tmp_df <- df_VACSI %>% filter(region_name == my_region_name, clage_vacsi !=0) %>%
      group_by(clage_vacsi) %>%
      select(jour, n_dose1) %>%
      group_split() %>%
      reduce(left_join, by = 'jour')
    
  }
  
  name_ages <- tmp_df  %>%  select(starts_with('clage_vacsi')) %>% filter(row_number() == 1) %>% as.numeric()
  tmp_mat <- tmp_df  %>%  select(starts_with('n_dose1')) %>% as.matrix()
  colnames(tmp_mat) <- name_ages
  rownames(tmp_mat) <- (tmp_df  %>%  select(jour))[[1]] %>% as.character()
  
  tmp_mat_2 <- cbind(rep(0, nrow(tmp_mat)),
                     rep(0, nrow(tmp_mat)),
                     tmp_mat[, '24'] + tmp_mat[, '29'],
                     tmp_mat[, '39'],
                     tmp_mat[, '49']/2, tmp_mat[, '49']/2,
                     tmp_mat[, '59']/2, tmp_mat[, '59']/2,
                     tmp_mat[, '64'], tmp_mat[, '69'],
                     tmp_mat[, '74'], tmp_mat[, '79'],
                     tmp_mat[, '80'])
  return(tmp_mat_2)
}

get_Mat_Rates_from_Mat_VaccinationStrategy <- function(RealMatVaccinationStrategy,
                                                       popSize.ageG){
 
  list_Mat_AgeOnly <- list(RealMatVaccinationStrategy)
  names(list_Mat_AgeOnly) <- 'Mat_VaccineStrategy_1'
  nVaccines <- length(list_Mat_AgeOnly)
  nDays <- nrow(list_Mat_AgeOnly[[1]])
  n.ageG <- length(popSize.ageG)
  
  list_Mat_Rates <- lapply(1:nVaccines, FUN = function(i){
    matrix(0, ncol = n.ageG, nrow = nDays)
  })
  names(list_Mat_Rates) <- names(list_Mat_AgeOnly)
  nNonVaccinated.ageG <- popSize.ageG
  for(iDay in 1:nDays){
    list_VectToVaccinate <- lapply(list_Mat_AgeOnly, FUN = function(l){
      l[iDay,]
    })
    list_Vectrates <- lapply(list_VectToVaccinate, FUN = function(l){
      nNewNonVaccinated.ageG <- nNonVaccinated.ageG - l
      log(nNonVaccinated.ageG) - log(nNewNonVaccinated.ageG)
    })
    ## Update the number of non vaccinated individuals in the different age groups
    nNonVaccinated.ageG <- nNonVaccinated.ageG - Reduce('+', list_VectToVaccinate)
    ## Update the list with the rates
    for(iVaccine in 1:nVaccines){
      list_Mat_Rates[[paste0('Mat_VaccineStrategy_', iVaccine)]][iDay, ] <- list_Vectrates[[paste0('Mat_VaccineStrategy_', iVaccine)]] 
    }
  }
  return(list_Mat_Rates)
}

get_Mat_Rates_RetrospectiveAndProspective <- function(my_region_name,
                                                      date_end_vaccine,
                                                      vect_maxVC,
                                                      seq_n_maxDosesPerDay,
                                                      df_Doses,
                                                      seq_DelayBetweenDoses,
                                                      seq_DateChangePace,
                                                      list_vaccine_priority){
  
  if(! (my_region_name %in% c('Metro', vect_name_region))){
    stop('Schedule not implemented for region: ', my_region_name)
  }
  
  ## Get the approximate matrix describing the number of doses received by the different individuals since the beginning of the 
  RealMatVaccinationStrategy <- get_Retrospective_Mat_VaccinationStrategy(my_region_name)
  RealMatRates <- get_Mat_Rates_from_Mat_VaccinationStrategy(RealMatVaccinationStrategy, get_populationVector(my_region_name))
  RealMatVaccinationStrategy_Metro <- get_Retrospective_Mat_VaccinationStrategy('Metro')
  
  DatesRetrospective <- as.Date(rownames(RealMatVaccinationStrategy))
  date_beginning_vaccine <- min(DatesRetrospective)
  date_beginning_projections_vaccination <- max(DatesRetrospective) + 1
  
  PropDosesToRegion <- sum(RealMatVaccinationStrategy)/sum(RealMatVaccinationStrategy_Metro)
  
  ## Correcting the population vector and the vector of maxVC to account for already vaccinated individuals
  popSize.ageG <- get_populationVector(my_region_name) - apply(RealMatVaccinationStrategy, 2, sum)
  maxVaccinated <- get_populationVector(my_region_name)*vect_maxVC
  maxVaccinated_RemoveAlreadyVaccinated <- maxVaccinated - apply(RealMatVaccinationStrategy, 2, sum)
  vect_maxVC_corr <- maxVaccinated_RemoveAlreadyVaccinated/popSize.ageG
  
  ## Correct the dataframe with the number of doses available
  df_Doses_RemoveRetrospective <- df_Doses[df_Doses$DateDelivery >= lubridate::floor_date(date_beginning_projections_vaccination, '%m'), ]
  
  ## Get the number of first doses that were distributed at the national level
  df_Doses_Retrospective <- (apply(df_Doses[df_Doses$DateDelivery < lubridate::floor_date(date_beginning_projections_vaccination, '%m'), 
                                                             grep(colnames(df_Doses), pattern = 'Doses_')],
                                     2, sum))
  DosesDistributedMetropolitanFrance <- sum(RealMatVaccinationStrategy_Metro)*2
  RemainingRetrospective <- df_Doses_Retrospective - df_Doses_Retrospective/sum(df_Doses_Retrospective)*DosesDistributedMetropolitanFrance
  
  df_Doses_RemoveRetrospective[, grep(names(df_Doses_RemoveRetrospective), pattern = 'Doses_')][1,] <- 
    df_Doses_RemoveRetrospective[, grep(names(df_Doses_RemoveRetrospective), pattern = 'Doses_')][1,] +
    RemainingRetrospective
  
  ## Distribute remaining doses across regions
  df_Doses_RemoveRetrospective[, grep(names(df_Doses_RemoveRetrospective), pattern = 'Doses_')] <- 
    PropDosesToRegion*df_Doses_RemoveRetrospective[, grep(names(df_Doses_RemoveRetrospective), pattern = 'Doses_')]
  
  
  ## Determine the change in the vaccination pace to mimic the distribution of the second doses
  LengthTimeWindowDistribution <- 28
  seq_DateChangePace <- rep(date_beginning_projections_vaccination + LengthTimeWindowDistribution - 1, 3)
  NSecondDosesToRemovePerDay <- sum(RealMatVaccinationStrategy[(nrow(RealMatVaccinationStrategy) - LengthTimeWindowDistribution + 1):nrow(RealMatVaccinationStrategy), ])/LengthTimeWindowDistribution

  tmp_seq_n_maxDosesPerDay_Before <- PropDosesToRegion*seq_n_maxDosesPerDay - seq_n_maxDosesPerDay/sum(seq_n_maxDosesPerDay)*NSecondDosesToRemovePerDay
  tmp_seq_n_maxDosesPerDay_After <- PropDosesToRegion*seq_n_maxDosesPerDay
  
  if(sum(tmp_seq_n_maxDosesPerDay_Before <0) >0){
    stop('Negative number of doses distributed in region ', my_region_name)
  }
  
  MatRatesProspective <- get_Mat_Rates_nVaccines_justAge_ChangePace(date_beginning_vaccine = date_beginning_projections_vaccination,
                                                                    date_end_vaccine = date_end_vaccine,
                                                                    vect_maxVC = vect_maxVC_corr,
                                                                    seq_n_maxDosesPerDay_Before = tmp_seq_n_maxDosesPerDay_Before,
                                                                    seq_n_maxDosesPerDay_After = tmp_seq_n_maxDosesPerDay_After,
                                                                    df_Doses = df_Doses_RemoveRetrospective,
                                                                    seq_DelayBetweenDoses = seq_DelayBetweenDoses,
                                                                    seq_DateChangePace = seq_DateChangePace,
                                                                    list_vaccine_priority = list_vaccine_priority,
                                                                    popSize.ageG = popSize.ageG)
  
  
  
  MatRatesAll <- rbind(RealMatRates[[1]], Reduce('+', MatRatesProspective))
  return(MatRatesAll)
}