# Sys.setenv(R_RGEOMORPHON_RUN_LONG_EXAMPLES = TRUE)
litedown::reactor(
    eval = (
        isTRUE(as.logical(
            Sys.getenv("R_RGEOMORPHON_RUN_LONG_EXAMPLES", unset = "FALSE")
        )) &&
            requireNamespace("terra", quietly = TRUE) &&
            all(nzchar(c(system.file(package = "future"),
                         system.file(package = "future.apply"), 
                         system.file(package = "parallel"))))
    )
)

library(rgeomorphon)

library(rgeomorphon)
library(terra)
library(future)
library(future.apply)

# Load the salton dataset and prepare it as a SpatRaster
data("salton", package = "rgeomorphon")
dem <- terra::rast(salton)
names(dem) <- "Elevation"
crs(dem) <- attr(salton, "crs")
ext(dem) <- attr(salton, "extent")

# By default, this small raster is processed in a single chunk
geomorphon_chunks_needed(dem)

# Scale up the memory needed (equivalent to number of input raster copies)
Sys.setenv(R_RGEOMORPHON_MEM_SCALE_NEED = 1e7)

# which will cause the chunking algorithm to divide the raster
geomorphon_chunks_needed(dem)

# Unset the environment variable
Sys.unsetenv("R_RGEOMORPHON_MEM_SCALE_NEED")

# Set up a multisession future plan with 4 workers
# This creates 4 background R sessions to do the work
future::plan(multisession, workers = 4)

system.time({
    g_parallel <- geomorphons(
        dem,
        search = 10,
        flat = 0.1,
        LAPPLY.FUN = function(X, FUN, ...) {
            future.apply::future_lapply(X, FUN, future.seed = TRUE, ...)
        },
        nchunk = 2
    )
})

# Shut down the parallel workers
future::plan(sequential)

# Inspect
terra::plot(g_parallel, main = "Geomorphons via Tiled Processing")

# Example using the base R parallel package
library(parallel)
cl <- makeCluster(4)

g_forms_par <- geomorphons(
    dem,
    search = 10,
    flat = 0.1,
    LAPPLY.FUN = function(X, FUN, ...) {
        parLapply(cl, X, FUN, ...)
    }
)

stopCluster(cl)

# Define a custom lapply-like function that adds reporting
reporting_lapply <- function(X, FUN, ...) {
    
    reporting_FUN <- function(i) {
        message(paste0("Starting tile #", i, " at ", Sys.time()))
        result <- FUN(i, ...)
        message(paste0("Finished tile #", i, " at ", Sys.time()))
        return(result)
    }

    lapply(X, reporting_FUN)
}

g_forms_reported <- geomorphons(
    dem,
    search = 10,
    flat = 0.1,
    LAPPLY.FUN = reporting_lapply
)

