#!/usr/bin/env lua
--
-- Copyright (c) 2020, Tano Systems. All Rights Reserved.
-- Anton Kikin <a.kikin@tano-systems.com>
--

local json = require "luci.jsonc"
local util = require("luci.util")

-- LLDPCLI commands
local function lldpcli_show(section, format)
	if not format then
		format = "plain"
	end

	return util.exec("lldpcli show " .. section .. " -f " .. format)
end

local methods = {
	getStatus = {
		call = function()
			local status = {
				statistics = json.parse(lldpcli_show("statistics", "json0")),
				neighbors  = json.parse(lldpcli_show("neighbors details", "json0")),
				interfaces = json.parse(lldpcli_show("interfaces", "json0")),
				chassis    = json.parse(lldpcli_show("chassis",    "json0"))
			}

			return status
		end
	}
}

local function parseInput()
	local parse = json.new()
	local done, err

	while true do
		local chunk = io.read(4096)
		if not chunk then
			break
		elseif not done and not err then
			done, err = parse:parse(chunk)
		end
	end

	if not done then
		print(json.stringify({ error = err or "Incomplete input" }))
		os.exit(1)
	end

	return parse:get()
end

local function validateArgs(func, uargs)
	local method = methods[func]
	if not method then
		print(json.stringify({ error = "Method not found" }))
		os.exit(1)
	end

	if type(uargs) ~= "table" then
		print(json.stringify({ error = "Invalid arguments" }))
		os.exit(1)
	end

	uargs.ubus_rpc_session = nil

	local k, v
	local margs = method.args or {}
	for k, v in pairs(uargs) do
		if margs[k] == nil or
		   (v ~= nil and type(v) ~= type(margs[k]))
		then
			print(json.stringify({ error = "Invalid arguments" }))
			os.exit(1)
		end
	end

	return method
end

if arg[1] == "list" then
	local _, method, rv = nil, nil, {}
	for _, method in pairs(methods) do rv[_] = method.args or {} end
	print((json.stringify(rv):gsub(":%[%]", ":{}")))
elseif arg[1] == "call" then
	local args = parseInput()
	local method = validateArgs(arg[2], args)
	local result, code = method.call(args)
	print((json.stringify(result):gsub("^%[%]$", "{}")))
	os.exit(code or 0)
end
