# parent frame test.R
#  GOAL:  To understand the different parent.frame environments. 
#---------------------------------------------------------------


#   #------------------------------------------------------------------------##
#   ###                       MOTIVATION: 
#   #------------------------------------------------------------------------##
#       I would like to be able to source functions from within functions, 
#       but that they not go too far into parent environments. 
#        
#       For example: I have a utils file located in a github repo, 
#       the file contains several functions which I would like to 
#       use in my script. 
#       If I use a function `source.url`  eg: `source.url("myGitURL")`
#       I want it to include those functions within my script, but not
#       within the environment calling my script. 
#       (ie, a simple way to do it is to use `envir= .GlobalEnv`, but 
#         that would replace any functions in .GlobalEnv with same name, 
#         plus that would be beyond the scope of my function).
#        
#       Thefore, I want to correctly master the parent.frame() levels to 
#       properly indicate where my functions should be located. 
#
#
#       Does it matter where the function was declared, or where it was invoked?
#   #------------------------------------------------------------------------##


# +---------------------------------------------------  
# +   ENVIRONMENTS
# +---------------------------------------------------  
  Lenv1 <- function() {
    # shows environment
    out <- capture.output(environment())
    cat("Lenv1 Env is ", out, "]$$\n")
    return(environment())
  }

  Lenv2 <- function() {
    # shows environment

    out <- capture.output(environment())
    cat("Lenv2 Env is ", out, "]$$\n")

    cat("\n","This is the return from Lenv1() within Lenv2:", "\n")
    print(Lenv1())

  }

  Lenv2()
# +---------------------------------------------------  


# +---------------------------------------------------  
# +   FUNCTIONS INSIDE FUNCTIONS
# +---------------------------------------------------  


hokusPokus.original <- function(tabs) { 
  cat(tbs(tabs),"I AM THE ORIGINAL\n", sep=""); 
}

Levs <- function(pLev, maxDepth, curDepth=0, showLoc=FALSE) {
  ins(curDepth)
  hokusPokus(curDepth)


  if (curDepth == maxDepth) {
    # declare the function
    func <- 'hokusPokus <- function(tabs) { cat(tbs(tabs),"\n",tbs(tabs),"I\'VE BEEN REPLACED!!\n",tbs(tabs),"˘˘˘˘˘˘˘˘˘˘˘˘\n", sep="")}'
    eval(parse(text=func), envir=parent.frame(pLev))
  } 

  # Go deeper
  if (curDepth < maxDepth)
    Levs(pLev, maxDepth, curDepth+1, showLoc)

  hokusPokus(curDepth)

  # Show location
  if (showLoc) {
    location <- capture.output(get("hokusPokus", pos=1))#$where
    cat(tbs(curDepth), "\thokusPokus has", length(location), "location(s): ", location)
  }

  outs(curDepth)
}

# RESET
g(p, m, c) %=% c(1, 1, 0)


#  calculated
## p <- m - c; 

predictions(p, m, c)
cat("\n\n\n"); hokusPokus <- hokusPokus.original; hokusPokus(0);
Levs(pLev=p, maxDepth=m, c, F); cat("\n=====================\nGLOBAL: "); hokusPokus(0); cat("=====================\n")
p

GOAL:
    I want the change to exist in Level c, but NOT in GlobalEnv 
    m (maxDepth) is the level in which the change will occur
    p should be a function of m and ; 
    Therefore p should be p <- (m - c)
explanations: 
  if c > m => change will never be called (essentially error)

# +---------------------------------------------------  




#---------------------------#
##############################

ins <- function(dpth) {
  t <- tbs(dpth)
  cat(t, "-------------\n", t, "INSIDE LEV ", dpth, "\n", sep="")
}

outs <- function(dpth) {
  t <- tbs(dpth)
  cat(t, "EXITNG LEV ", dpth, "\n", t, "-------------\n", sep="")
}

predictions <- function(p, m, c) {
  # cat("The level that will change is `p` up from `m`, `m` being where the change was called for.\n",
  #     "that is, the change will happen at m-p.",
  #     "If m-p ≤ 0, then the GlobalEnv will be changed. Otherwise, it will not.\n\n") 
  cat("Level that will change: ", (LevelChanged <- (m - p) ),"\n", sep="")
  cat("Global threshold is: ", (GlobalThresh <- (m - c) - p), ifelse(GlobalThresh>-1, ". => GlobalEnv will NOT change", ". => GlobalEnv WILL change"),"\n", sep="")
}

cat()
    cat("****\n-------------------\nINSIDE Lf2\n")

# this function is in utilsRS.R, but replicated here just in case
tbs <- function(n)  {
  # returns a string of n-many tabs, concatenated together
  return(paste0(rep("\t", n), collapse=""))  
}


