--- Provides the ability to localize and export the scope of a file.
--- Usage:
---
--- -- Make global scope local to the file, with metatable.__index of _E (The Addon's global environment).
--- -- Insert at the beginning of the file.
--- local AddOnName, nsVars = ...
--- nsVars[AddOnName].localize()
---
--- -- Make all initialized (global) objects available to _E (The Addon's global environment).
--- -- Insert at the end of the file.
--- export()
---
--- -- Make object available to _E (The Addon's global environment), access using GLOBAL_KEY.
--- -- Insert after initialized object.
--- export("GLOBAL_KEY", object)
local AddOnName, nsVars = ...
nsVars[AddOnName] = {
  AddOnName = AddOnName,
  ss = nsVars.SS,
}

setfenv(1, setmetatable(nsVars[AddOnName], { __index = _G }))

_E = nsVars[AddOnName]

do
  local function setfuncenvs(o, e, deep)
    if type(o) == "function" and getfenv(o) ~= _G then
      -- Set the operating environment of functions.
      setfenv(o, e)
    elseif deep and type(o) == "table" then
      -- Search for function values.
      for _, v in pairs(o) do
        setfuncenvs(v, e, deep)
      end
    end
  end

  --- Exports an object to _E[index].
  --- if no parameters are given, exports all global objects to _E.
  ---@param index string The object index for _E.
  ---@param object any The object.
  ---@param deep boolean Flag to search table values for functions. (Default true)
  function export(index, object, deep)
    deep = deep ~= false

    if index then
      assert(type(index) == "string" or type(index) == "number")
      setfuncenvs(object, _E, deep)
      _E[index] = object
    elseif getfenv(2) ~= _G then
      for k, v in pairs(getfenv(2)) do
        setfuncenvs(v, _E, deep)
        _E[k] = v
      end
    end
  end

  --- Exports an object to _G[index].
  --- if no parameters are given, exports all global objects to _G.
  ---@param index string The object index for _G.
  ---@param object any The object.
  ---@param deep boolean Flag to search table values for functions. (Default true)
  function gexport(index, object, deep)
    deep = deep ~= false

    if index then
      assert(type(index) == "string" or type(index) == "number")
      setfuncenvs(object, _G, deep)
      rawset(_G, index, object)
    elseif getfenv(2) ~= _G then
      for k, v in pairs(getfenv(2)) do
        setfuncenvs(v, _G, deep)
        rawset(_G, k, v)
      end
    end
  end
end

--- Sets a file's global scope to a new table, with a metatable.__index of _E.
function localize()
  setfenv(2, setmetatable({}, { __index = _E }))
end
