# recipe: the recipe as returned by prepare_outputs()
divide_recipe <- function(recipe) {

  ## TODO: Implement dependent vs independent verifications?
  info(recipe$Run$logger, "Splitting recipe in single verifications.")
  beta_recipe <- list(Description = append(recipe$Description, 
                                           list(Origin = paste("Atomic recipe,",
                                                               "split from:", 
                                                               recipe$name, 
                                                               collapse = ""))),
                      Analysis = list(Horizon = recipe$Analysis$Horizon,
                                      Variables = NULL,
                                      Datasets = NULL,
                                      Time = NULL,
                                      Region = NULL,
                                      Regrid = recipe$Analysis$Regrid,
                                      Workflow = recipe$Analysis$Workflow,
                                      ncores = recipe$Analysis$ncores,
                                      remove_NAs = recipe$Analysis$remove_NAs,
                                      Output_format = 
                                        recipe$Analysis$Output_format),
                      Run = recipe$Run[c("Loglevel", "output_dir", "Terminal",
                                         "code_dir", "logfile", "filesystem")])
  
  # duplicate recipe by independent variables:
  # If a single variable is not given inside a list, rebuild structure
  if (any(c("name", "freq", "units") %in% names(recipe$Analysis$Variables))) {
    variables <- recipe$Analysis$Variables
    recipe$Analysis$Variables <- NULL
    recipe$Analysis$Variables[[1]] <- variables
  }
  all_recipes <- rep(list(beta_recipe), length(recipe$Analysis$Variables))
  for (var in 1:length(recipe$Analysis$Variables)) {
    all_recipes[[var]]$Analysis$Variables <- recipe$Analysis$Variables[[var]]
  }

  # duplicate recipe by Datasets:
  # check Systems
  # If a single system is not given inside a list, rebuild structure
  if (any(c("name", "member") %in% names(recipe$Analysis$Datasets$System))) {
    system <- recipe$Analysis$Datasets$System
    recipe$Analysis$Datasets$System <- NULL
    recipe$Analysis$Datasets$System[[1]] <- system
  }
  # Modify the saving of the individual models in case multimodel is yes or both
  if (recipe$Analysis$Datasets$Multimodel$execute %in% c(TRUE, 'both')) {
    # Create directory for multimodel recipes
    dir.create(paste0(recipe$Run$output_dir, "/logs/recipes/multimodel/"),
               recursive = TRUE)
    n_models <- length(recipe$Analysis$Datasets$System) + 1
    mm <- tolower(recipe$Analysis$Datasets$Multimodel$approach)
  } else {
    n_models <- length(recipe$Analysis$Datasets$System)
    mm <- FALSE
  }
  for (sys in 1:n_models) {
    for (reci in 1:length(all_recipes)) {
      if (sys == length(recipe$Analysis$Datasets$System)+1) {
        # seasonal only needs the model name; decadal also needs the members
        if (tolower(recipe$Analysis$Horizon) == 'seasonal') {
          m <- unlist(recipe$Analysis$Datasets$System)
        } else if (tolower(recipe$Analysis$Horizon) == 'decadal') {
          m <- recipe$Analysis$Datasets$System
        }
        all_recipes[[reci]]$Analysis$Datasets <- 
          list(System = list(name = 'Multimodel',
                             models = m),
               Multimodel = recipe$Analysis$Datasets$Multimodel,
               Reference = NULL)
      } else {
        all_recipes[[reci]]$Analysis$Datasets <- 
          list(System = recipe$Analysis$Datasets$System[[sys]],
               Multimodel = list(execute ='no'),
               Reference = NULL)
      }
    }
    if (sys == 1) {
      recipes <- all_recipes
    } else {
      recipes <- append(recipes, all_recipes)
    }
  }
  all_recipes <- recipes
  rm(list = 'recipes')
  for (reci in 1:length(all_recipes)) {
    if (!isFALSE(mm) && tolower(all_recipes[[reci]]$Analysis$Datasets$System$name) != 'multimodel') {
      all_recipes[[reci]]$Analysis$Workflow[[recipe$Analysis$Datasets$Multimodel$createFrom]]$save <- 'all'
      if (mm %in% c('mean','median')) {
        all_recipes[[reci]]$Analysis$Workflow$Probabilities$save <- 'all'
      }
    } 
  }
  
  # Check references
  # If a single reference is not given inside a list, rebuild structure
  if (c("name") %in% names(recipe$Analysis$Datasets$Reference)) {
    reference <- recipe$Analysis$Datasets$Reference
    recipe$Analysis$Datasets$Reference <- NULL
    recipe$Analysis$Datasets$Reference[[1]] <- reference
  }

  for (ref in 1:length(recipe$Analysis$Datasets$Reference)) {
    for (reci in 1:length(all_recipes)) {
      all_recipes[[reci]]$Analysis$Datasets$Reference <- 
        recipe$Analysis$Datasets$Reference[[ref]]
    }
    if (ref == 1) {
        recipes <- all_recipes
    } else {
        recipes <- append(recipes, all_recipes)
    }
  }
  all_recipes <- recipes
  rm(list = 'recipes')

  # Duplicate recipe by Region
  recipes <- list()
  if (any(c("latmin", "latmax", "lonmin", "lonmax") %in% 
          names(recipe$Analysis$Region))) {
    region <- recipe$Analysis$Region
    recipe$Analysis$Region <- NULL
    recipe$Analysis$Region[[1]] <- region
  }
  for (reg in 1:length(recipe$Analysis$Region)) {
    for (reci in 1:length(all_recipes)) {
      all_recipes[[reci]]$Analysis$Region <- recipe$Analysis$Region[[reg]]
    }
    if (reg == 1) {
      recipes <- all_recipes
    } else {
      recipes <- append(recipes, all_recipes)
    }
  }

  all_recipes <- recipes
  rm(list = 'recipes')
  # Duplicate recipe by start date
  if (tolower(recipe$Analysis$Horizon) == 'seasonal') {
    for (sdate in 1:length(recipe$Analysis$Time$sdate)) {
      for (reci in 1:length(all_recipes)) {
      all_recipes[[reci]]$Analysis$Time <-
        list(sdate = recipe$Analysis$Time$sdate[[sdate]],
             fcst_year = recipe$Analysis$Time$fcst_year,
             hcst_start = recipe$Analysis$Time$hcst_start,
             hcst_end = recipe$Analysis$Time$hcst_end,
             ftime_min = recipe$Analysis$Time$ftime_min,
             ftime_max = recipe$Analysis$Time$ftime_max)
      }
      if (sdate == 1) {
        recipes <- all_recipes
      } else {
        recipes <- append(recipes, all_recipes)
      } 
    }
    all_recipes <- recipes
    rm(list = 'recipes')
  } else if (tolower(recipe$Analysis$Horizon) == 'decadal') {
    for (reci in 1:length(all_recipes)) {
      all_recipes[[reci]]$Analysis$Time <-
        list(fcst_year = recipe$Analysis$Time$fcst_year,
             hcst_start = recipe$Analysis$Time$hcst_start,
             hcst_end = recipe$Analysis$Time$hcst_end,
             ftime_min = recipe$Analysis$Time$ftime_min,
             ftime_max = recipe$Analysis$Time$ftime_max)
    }
  } else if (tolower(recipe$Analysis$Horizon) == "subseasonal") {
    for (sdate in 1:length(recipe$Analysis$Time$sdate)) {
      # If 'sdate' is a year, calculate all days in that year that are the same as
      # the day specify in 'week_day' (by default, Thursday) 
      DAYS_OF_WEEK <- list(monday = 1, tuesday = 2, wednesday = 3, thursday = 4,
                           friday = 5, saturday = 6, sunday = 0)
      if (nchar(recipe$Analysis$Time$sdate[sdate]) == 4) {
        sdate_weekday <- DAYS_OF_WEEK[[tolower(recipe$Analysis$Time$week_day)]]
        days <- as.POSIXlt(paste(recipe$Analysis$Time$sdate[sdate],
                           1:366, sep = "-"), format = "%Y-%j")
        # Remove extra NA days if sdate is not a leap year:
        days <- days[!is.na(days)]
        day_of_the_week_ini <- days[days$wday == sdate_weekday]
      } else if (nchar(recipe$Analysis$Time$sdate[sdate]) == 8) {
        day_of_the_week_ini <- as.POSIXct(as.character(recipe$Analysis$Time$sdate[sdate]),
                                          format = "%Y%m%d",
                                          origin = '1970-01-01',
                                          tz = 'UTC')
      } else {
        stop("what other cases can exist in subaseasonal?")
      }
    }
    for (sdate in 1:length(day_of_the_week_ini)) {
      for (reci in 1:length(all_recipes)) {
        all_recipes[[reci]]$Analysis$Time <-
          list(sdate = format(day_of_the_week_ini[sdate], "%Y%m%d"),
               fcst_year = recipe$Analysis$Time$fcst_year,
               hcst_start = recipe$Analysis$Time$hcst_start,
               hcst_end = recipe$Analysis$Time$hcst_end,
               ftime_min = recipe$Analysis$Time$ftime_min,
               ftime_max = recipe$Analysis$Time$ftime_max,
               week_day = recipe$Analysis$Time$week_day,
               sweek_window = recipe$Analysis$Time$sweek_window, 
               sday_window =recipe$Analysis$Time$sday_window)
      }
      if (sdate == 1) {
        recipes <- all_recipes
      } else {
        recipes <- append(recipes, all_recipes)
      }
    }
    all_recipes <- recipes
    rm(list = 'recipes')  
  } # Rest of horizons
  # Save all recipes in separate YAML files
  chunk <- 1
  split <- 1
  chunk_to_recipe <- list()
  split_to_recipe <- list()
  total_models <- length(recipe$Analysis$Datasets$System)
  for (reci in 1:length(all_recipes)) {
    ## TODO: Document
    recipe_model <- paste0("sys-",
                           gsub('\\.', '', all_recipes[[reci]]$Analysis$Datasets$System$name))
    # 
    recipe_split <- paste0("_ref-", all_recipes[[reci]]$Analysis$Datasets$Reference$name,
                           "_var-", all_recipes[[reci]]$Analysis$Variables$name,
                           "_reg-", all_recipes[[reci]]$Analysis$Region$name,
                           "_sdate-", all_recipes[[reci]]$Analysis$Time$sdate)
    recipe_name <- paste0(recipe_model, recipe_split)
    

    if (all_recipes[[reci]]$Analysis$Datasets$System$name == 'Multimodel') {
      recipe_dir <- paste0(recipe$Run$output_dir, "/logs/recipes/multimodel/")
      split_to_recipe[split] <- recipe_split
      split <- split + 1
    } else {
      recipe_dir <- paste0(recipe$Run$output_dir, "/logs/recipes/")
      chunk_to_recipe[chunk] <- recipe_name
      chunk <- chunk + 1
    }
    write_yaml(all_recipes[[reci]], 
               paste0(recipe_dir, "atomic_recipe_", recipe_name, ".yml"))
  }

  # Print information for user
  info(recipe$Run$logger,
       paste("The main recipe has been divided into", length(chunk_to_recipe),
             "single model atomic recipes, plus", length(split_to_recipe),
             "multi-model atomic recipes."))
  text <- paste0("Check output directory ", recipe$Run$output_dir,
                 "/logs/recipes/ to see all the individual atomic recipes.")
  info(recipe$Run$logger, text)
  ## TODO: Change returns?
  return(list(n_atomic_recipes = length(chunk_to_recipe), # length(all_recipes)
              outdir = recipe$Run$output_dir,
              chunk_to_recipe = chunk_to_recipe,
              split_to_recipe = split_to_recipe))
}

