--- change_modules
-- @module change_modules

local change_modules = {
    name = "Change modules",
    slug = "change_modules",
    desc = "Add or remove modules from the org",
    hide = false;
}

change_modules.data = {
   result = nil,
   modules_before = {},
   modules_after = {},
   summary = "",
}

change_modules.config = {
   approval_module = false
}

--- Initiate change in modules.
-- Either adds or removes module depending on user input
-- @function change_modules:initiate
-- @param result Callback if this module is embedded in other modules
function change_modules:initiate(result)
   self.data.result = result
   self.data.add_modules = {}
   self.data.remove_modules = {}
   local modules_before = {}
   local modules_after = {}
   -- generate self.config.modules table
   for k, module in pairs(modpol.modules) do
      if not modpol.modules[module.slug].hide then
         local in_org = false
         if self.org.policies[module.slug] then
            in_org = true
         end
         table.insert(
            modules_before,
            {module.name.." ["..module.slug.."]", in_org})
      end
   end
   -- send query to user
   modpol.interactions.checkbox_query(
      self.initiator,
      "Check the modules to activate in this org:",
      modules_before,
      function(input)
         -- identify changes
         modules_after = input
         for i,v in ipairs(modules_after) do
            if v[2] ~= modules_before[i][2] then
               if v[2] then
                  table.insert(self.data.add_modules, v[1])
               else
                  table.insert(self.data.remove_modules, v[1])
               end
            end
         end
         -- abort if no changes
         if #self.data.add_modules == 0
            and #self.data.remove_modules == 0 then
            modpol.interactions.message(
               self.initiator, "No module changes proposed")
            modpol.interactions.org_dashboard(
               self.initiator, self.org.id)
            self.org:delete_process(self.id)
            return
         end
         -- proceed with approval
         local query = "Accept module changes in org "..
            self.org.name.."?"
         self.data.summary = ""
         if #self.data.add_modules > 0 then
            self.data.summary = self.data.summary.."\nAdd: "..
               table.concat(self.data.add_modules,", ")
         elseif #self.data.remove_modules > 0 then
            self.data.summary = "\nRemove: "..
               table.concat(self.data.remove_modules,", ")
         end
         self:call_module(
            self.config.approval_module,
            self.initiator,
            {
               prompt = query..self.data.summary
            },
            function()
               self:implement_change()
         end)
         modpol.interactions.org_dashboard(
            self.initiator, self.org.id)
   end)
end

function change_modules:implement_change()
   for i,v in ipairs(self.data.add_modules) do
      local slug = string.match(v,"%[(.+)%]")
      self.org.policies[slug] = {}
      table.sort(self.org.policies)
   end
   for i,v in ipairs(self.data.remove_modules) do
      local slug = string.match(v,"%[(.+)%]")
      self.org.policies[slug] = nil
      table.sort(self.org.policies)
   end
   -- announce and shut down
   modpol.interactions.message_org(
      self.initiator,
      self.org.id,
      "Module changes applied to org "..self.org.name..":"..
      self.data.summary)
   if self.data.result then self.data.result() end
   self.org:delete_process(self.id)
end
   
modpol.modules.change_modules = change_modules