util.missionCommands = {}

-- holds all registered commands
util.missionCommands.reg = {}

--- generates all possible submenu paths and packs them all in an array
---
--- INFO: if the path is the root direcoty this function retuns a table with index 1 = "/" (home)
--- @param menuPth string original path
--- @return string[] @ordered subpath array
function util.missionCommands.getSubPths(menuPth)
    if type(menuPth) ~= "string" then error(util.error.argErr(menuPth, "string", 1)) end

    local subPths = {}
    local dirs = util.misc.split(menuPth, "/")

    -- append / and name to last path. Start with "" (when no prev element)
    for _i, dir in pairs(dirs) do
        subPths[#subPths + 1] = (subPths[#subPths] or "") .. "/" .. dir
    end

    return subPths
end

--- adds all nessacary sub menus
--- @param menuPth string sub menu to append. Function will automatically add all nessacary menus
--- @return nil
function util.missionCommands.addSubPthSave(menuPth)
if type(menuPth) ~= "string" then error(util.error.argErr(menuPth, "string", 1)) end

    -- get all possible sub path of current path + their names
    local subPths, subPthsNames = util.missionCommands.getSubPths(menuPth), util.misc.split(menuPth, "/")

    -- for every subpath check if exist. And create if nessacary
    for i, subPth in pairs(subPths) do
        -- If not exist and not root => create
        if util.missionCommands.reg[subPth] == nil and subPth ~= "/" then
            -- get DCS display name and DCS Path objects and create subpath
            local DCSName, DCSPath = subPthsNames[i], util.missionCommands.reg[subPths[i - 1]]
            util.missionCommands.reg[subPth] = missionCommands.addSubMenu(DCSName, DCSPath)
        end
    end

    return nil
end

--- removes all nessacary sub menus
--- @param menuPth string sub menu to remove. Function will automatically remove all nessacary menus
--- @return nil
function util.missionCommands.remSubPthSave(menuPth)
    if type(menuPth) ~= "string" then error(util.error.argErr(menuPth, "string", 1)) end
    -- all menus are still existent => check if ech one is used by a different endpoint
    local subPths = util.missionCommands.getSubPths(menuPth)

    -- iterate (reversed) through all paths
    for i=#subPths, 1, -1 do
        -- check if path has to be deleted (default true unil use detected)
        local currPth, delete = subPths[i], true

        -- check if any other path (except self) is using current branch
        for pth, path in pairs(util.missionCommands.reg) do
            if pth:find(currPth) ~= nil and pth ~= currPth then
                delete = false
                break
            end
        end

        -- if no use detected delete from mission commands and reg
        if delete then
            missionCommands.removeItem(util.missionCommands.reg[currPth])
            util.missionCommands.reg[currPth] = nil
        end
    end

    return nil
end

--- adds a menu Point and all nessacary Submenus to DCS
---
--- EXAMPLE: menuPath = "/this/is/aPath", name = "myTrigger" represents the Submenu structure this.is.aPath.myTrigger
--- @param menuPth string the path to the menu (excluding name) in form "/this/is/aPath"
--- @param name string the name DCS should display your endpoint
--- @param content? fun(p:any[]|nil) function you want the menu to perform on action
--- @vararg any parameters which are supplied when the functiob is called (see DCS missionCommands.addCommand)
--- @return nil
function util.missionCommands.add(menuPth, name, content, ...)
    if type(menuPth) ~= "string" then error(util.error.argErr(menuPth, "string", 1)) end
    if type(name) ~= "string" then error(util.error.argErr(name, "string", 2)) end
    -- save add all nessacary sub paths
    util.missionCommands.addSubPthSave(menuPth)

    -- should always result in nil if menuPath = "/" wich is wanted
    local path = util.missionCommands.reg[menuPth]

    -- create current path with created subpaths
    util.missionCommands.reg[menuPth .. "/" .. name] = missionCommands.addCommand(name, path, content, unpack(arg))

    return nil
end

--- removes a menu Point and all unused Submenus from DCS
---
--- EXAMPLE: menuPath = "/this/is/aPath", name = "myTrigger" represents the Submenu structure this.is.aPath.myTrigger
--- @param menuPth string the path to the menu (excluding name) in form "/this/is/aPath"
--- @param name string the name DCS is currently displaying your endpoint
--- @return nil
function util.missionCommands.remove(menuPth, name)
    if type(menuPth) ~= "string" then error(util.error.argErr(menuPth, "string", 1)) end
    if type(name) ~= "string" then error(util.error.argErr(name, "string", 2)) end

    -- remove the endpoint itself from mission commands and reg
    missionCommands.removeItem(util.missionCommands.reg[menuPth .. "/" .. name])
    util.missionCommands.reg[menuPth .. "/" .. name] = nil

    -- save remove all nessacary sub paths
    util.missionCommands.remSubPthSave(menuPth)

    return nil
end