#! /usr/bin/lua

local nixio = require("nixio")

function execute(args)
    local result = { changed = false, failed = false }

    local port_files = {}
    port_files["/etc/config.mesh/_setup.ports.dmz"] = {}
    port_files["/etc/config.mesh/_setip.ports.nat"] = {}

    if not args.interface then
        result.failed = true
        result.msg = "Missing interface"
    elseif not args.type or not (args.type == "tcp" or args.type == "udp" or args.type == "both") then
        result.failed = true
        result.msg = "Type must be 'tcp', 'udp' or 'both'"
    elseif not args.port then
        result.failed = true
        result.msg = "Missing outside port"
    elseif not args.address then
        result.failed = true
        result.msg = "Missing address"
    elseif not args.lanport then
        result.failed = true
        result.msg = "Missing lan port"
    else
        for file, tbl in pairs(port_files)
        do
            if nixio.fs.stat(file) then
                for line in io.lines(file)
                do
                    tbl[#tbl + 1] = line
                end
            end
        end

        local descriptor = args.interface .. ":" .. args.type .. ":" .. args.port .. ":" .. args.address .. ":" .. args.lanport .. ":1"

        if args.state == "present" then
            for _, tbl in pairs(port_files)
            do
                local found = false
                for idx, line in ipairs(tbl)
                do
                    if line == descriptor then
                        found = true
                        break
                    end
                end
                if not found then
                    tbl[#tbl + 1] = descriptor
                    result.changed = true
                end
            end
        elseif args.state == "absent" then
            for _, tbl in pairs(port_files)
            do
                for idx, line in ipairs(tbl)
                do
                    if line == descriptor then
                        table.remove(tbl, idx)
                        result.changed = true
                        break
                    end
                end
            end
        else
            result.failed = true
            result.msg = "Unknown state"
        end

        if result.changed then
            for file, tbl in pairs(port_files)
            do
                if nixio.fs.stat(file) then
                    local f = io.open(file, "w")
                    if f then
                        for _, line in ipairs(tbl)
                        do
                            f:write(line .. "\n")
                        end
                        f:close()
                    end
                end
            end
        end
    end

    return result
end

-- Boilerplate below --

local json = require("luci.jsonc")

local success, result = pcall(execute, json.parse([[<<INCLUDE_ANSIBLE_MODULE_JSON_ARGS>>]]))
if not success then
    result = {
        failed = true,
        changed = false,
        msg = result
    }
else
    if result.failed ~= false then
        result.failed = true
    end
    if result.changed ~= false then
        result.changed = true
    end
end
io.write(json.stringify(result))
