#!/usr/bin/env lua

local json = require "luci.jsonc"
local fs   = require "nixio.fs"
local sys = require "luci.sys"
local ut = require "luci.util"

local function readfile(path)
	local s = fs.readfile(path)
	return s and (s:gsub("^%s+", ""):gsub("%s+$", ""))
end

local methods = {
	getMwan3Policy = {
		call = function()
			local sys = require "luci.sys"
			local policy = luci.sys.exec("mwan3 policies | grep -e '^p.*' | cut -d ':' -f1 | xargs echo -n")
			return { result = policy }
		end
	},

	getIpsecStatus = {
		call = function()
			local sys = require "luci.sys"
			local uci = require "uci"
			local data = {}
			local x = uci.cursor()

			x:foreach('ipsec', 'ipsec', function(s)
				local section = s.conn
				local enable = s.enable
				data[section] = {}
				data[section]['enable'] = enable
				if enable ~= '0' then
					data[section]['status'] = luci.sys.exec("cat /var/ipsec/%q/status 2>/dev/null | xargs echo -n" % section)
					data[section]['tstatus'] = luci.sys.exec("cat /var/ipsec/%q/tstatus 2>/dev/null | xargs echo -n" % section)
					data[section]['uptime'] = luci.sys.exec("cat /var/ipsec/%q/uptime 2>/dev/null | xargs echo -n" % section)
					data[section]['tunnel'] = luci.sys.exec("cat /var/ipsec/%q/tunnel 2>/dev/null | xargs echo -n" % section)
					data[section]['inputBytesPkts'] = luci.sys.exec("cat /var/ipsec/%q/input_bytes_pkts 2>/dev/null | xargs echo -n" % section)
					data[section]['outputBytesPkts'] = luci.sys.exec("cat /var/ipsec/%q/output_bytes_pkts 2>/dev/null | xargs echo -n" % section)
					data[section]['ike'] = luci.sys.exec("cat /var/ipsec/%q/ike 2>/dev/null | xargs echo -n" % section)
					data[section]['esp'] = luci.sys.exec("cat /var/ipsec/%q/esp 2>/dev/null | xargs echo -n" % section)
				end
			end
			)
			return { result = data }
		end
	},

	setIpsecInterfaceAction = {
		args = { section = "", action = "" },
		call = function(args)
			local sys = require "luci.sys"
			local res = {}
			local section = args.section
			local action = args.action

			if action == "Connect" then
				luci.sys.exec("uci set ipsec.%q.enable=1" %section)
				luci.sys.exec("uci commit ipsec.%q.enable" %section)
			elseif action == "Disconnect" then
				luci.sys.exec("uci set ipsec.%q.enable=0" %section)
				luci.sys.exec("uci commit ipsec.%q.enable" %section)
			elseif action == "Delete" then
				luci.sys.exec("uci set ipsec.%q.enable=0" %section)
				luci.sys.exec("uci commit ipsec.%q.enable" %section)
			end

			comd="/usr/sbin/ipsec1 "..action.." "..section.." ".."&"
			luci.sys.call(comd)
			return { result = "OK" }
		end
	},

	getScepCertInfo = {
		call = function()
			local sys = require "luci.sys"
			local uci = require "uci"
			local data = {}
			local x = uci.cursor()

			x:foreach('scep', 'cert', function(s)
				local name = s.name
				local subject
				if s.enroll_status == '1' then
					data[name] = {}
					data[name]['key'] = luci.sys.exec("uci get scep.%q.key | xargs echo -n" %name)
					subject = luci.sys.exec("cat /etc/scep/%q/subject | xargs echo -n" %name)
					data[name]['subject'] =  "\"" .. subject .. "\""
				end
			end
			)

			return { result = data }
		end
	},

	getScepEnrolledCerts = {
		call = function()
			local sys = require "luci.sys"
			local uci = require "uci"
			local res = {}
			local x = uci.cursor()

			x:foreach('scep', 'cert', function(s)
				local name = s.name
				if s.enroll_status == '1' then
					table.insert(res, name)
				end
			end
			)

			return { result = res }
		end
	},

	getCertSubject = {
		args = { name = "" },
		call = function(args)
			local sys = require "luci.sys"
			local certname = args.name
			local subject = luci.sys.exec("cat /etc/scep/%q/subject | xargs echo -n" %certname)
			local subjname = "\"" .. subject .. "\""
			return { result = subjname }
		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
