#!/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 = {
	sendSms = {
		args = { mobile = "none", message = "none" },
		call = function(args)
			--Writing message into file then getting with cat command.
			--It is to overcome special char handling issue.
			local cmd="AT#SENDSMS=\"" .. tostring(args.mobile) .. "\"" .. tostring(args.message)
			file = io.open("/tmp/.smscmd", "w")
			file:write(cmd)
			file:close()

			ip=ut.trim(luci.sys.exec("uci get network.lan.ipaddr"))
			port=ut.trim(luci.sys.exec("uci get sms.@sms_over_lan[0].port"))
			comm="cat /tmp/.smscmd  | nc " .. ip .. " " .. port

			luci.sys.call(comm)

			return { result = "OK" }
		end
	},

	readSms = {
		call = function()
			local res = {  }
			local result = {  }
			local count = 0

			for filename in io.popen([[ls -t /tmp/sms_store_folder/smsfile_*]]):lines() do
				local data={}
				count = string.sub(filename, string.find(filename, "[0-9]+"))
        			line = readfile(filename)

				seq, date, time, number, message = line:match("([^,]+),([^,]+),([^,]+),([^,]+),(.*)")

				if seq and date and time and number and message then
					data["seq"] = count
					data["time"] = date .. " " .. time
					data["number"] = number
					data["message"] = message
					table.insert(res,data)
				end
			end
			return { result = res }
		end
	},

	deleteSms = {
		args = { smsno = "0" },
                call = function(args)
			if tostring(args.smsno) == "ALL" then
				luci.sys.exec("rm -f /tmp/sms_store_folder/smsfile_*")
				return { result = "OK" }
			else
				local filepath = "/tmp/sms_store_folder/smsfile_" .. tostring(args.smsno)
				if fs.readfile(filepath) then
					luci.sys.exec("rm -f " .. filepath)
					return { result = "OK" }
				else
					return { result = "Error" }
				end
			end
		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
