#! /usr/bin/lua

local uci = require("uci")
local nixio = require("nixio")

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

    local service_files = {
        ["/etc/config.mesh/_setup.services.dmz"] = {},
        ["/etc/config.mesh/_setup.services.nat"] = {}
    }

    if not args.name then
        result.failed = true
        result.msg = "Missing name"
        return result
    end

    local link, protocol, hostname, path, port
    if args.url then
        link = 1
        local p, rest = args.url:match("^(%w+)://(.+)$")
        if p then
            protocol = p
            local h, p, r = rest:match("^(.+):(%d+)(.*)")
            if h and p then
                hostname = h
                port = tonumber(p)
                path = r:sub(2)
            else
                local h, p = rest:match("^(.+)(/.*)")
                if h and p then
                    hostname = h
                    port = protocol == "http" and 80 or 0
                    path = p:sub(2)
                end
            end
        end
        if not protocol or not hostname then
            result.failed = true
            result.msg = "Bad url: " .. args.url
            return result
        end
    else
        protocol = args.protocol or "http"
        hostname = args.hostname or uci.cursor("/etc/local/uci"):get("hsmmmesh", "settings", "node")
        port = args.port or 8080
        path = args.path or ""
        if args.link ~= nil then
            link = args.link and 1 or 0
        elseif args.path or args.port or args.hostname or args.protocol then
            link = 1
        else
            link = 0
        end
    end
    local descriptor = string.format("%s|%d|%s|%s|%d|%s", args.name, link, protocol, hostname, port, path)

    -- Read in services
    for file, tbl in pairs(service_files)
    do
        if nixio.fs.stat(file) then
            for line in io.lines(file)
            do
                tbl[#tbl + 1] = line
            end
        end
    end

    if args.state == "present" then
        for _, tbl in pairs(service_files)
        do
            local found = false
            for idx, line in ipairs(tbl)
            do
                if line == descriptor then
                    found = true
                    break
                elseif line:match("^([^|]+)") == args.name then
                    -- Entry with the same name is different, so replace the old one
                    table.remove(tbl, idx)
                    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(service_files)
        do
            for i, line in ipairs(tbl)
            do
                if line:match("^([^|]+)") == args.name then
                    result.changed = true
                    table.remove(tbl, idx)
                    break
                end
            end
        end
    else
        result.failed = true
        result.msg = "Unknown state"
    end

    -- Write new services is there was a change
    if result.changed then
        for file, tbl in pairs(service_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

    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))
