#!/usr/bin/env lua

local json = require "luci.jsonc"
local fs   = require "nixio.fs"

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

local methods = {
	getServiceList = {
		args = { service = "none", action = "none" },
		call = function(args)
		local sys = require "luci.sys"
		local res = {}
		function scandir(directory)
			local i, t, popen = 0, {}, io.popen
			local pfile = popen('ls "'..directory..'"')
			for filename in pfile:lines() do
				i = i + 1
				t[i] = filename
			end
			pfile:close()
			return t
		end
		if args.service and args.action then
			local cmd="/etc/init.d/" .. args.service .. " " .. args.action
			luci.sys.exec(cmd)
				res[1]='OK'
			else
				res=scandir("/etc/init.d/")
			end
			return { result = res }
		end
	},
        getCFlowList = {
                call= function()
                        local fileContent = {}
                        local fs = require "nixio.fs"
                        local sys = require "luci.sys"
                        fileContent[0] = readfile("/var/run/mach10.pid") and "Running" or "Inactive"
                        fileContent[1] = readfile("/tmp/mach10.errors",1024) or "None"

                        local timestamp = readfile("/tmp/mach10.status_update",1024)
                        fileContent[2] = ""
                        if timestamp then
                                fileContent[2]=luci.sys.exec("/usr/sbin/timediff.sh /tmp/mach10.status_update")
                        end

                        timestamp =  readfile("/tmp/mach10.check_update",1024)
                        fileContent[3]=""
                        if timestamp then
                                fileContent[3]=luci.sys.exec("/usr/sbin/timediff.sh /tmp/mach10.check_update")
                        end

                        fileContent[4] = readfile("/tmp/mach10.available_firmware",1024) or "<None>"
                        fileContent[5] = readfile("/tmp/mach10.available_config",1024) or "<None>"
                        fileContent[6] = readfile("/tmp/luci_message_cflow",1024) or ""
                        return {result = fileContent }
                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
