#!/usr/bin/env lua

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

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

local methods = {

    getBtSerialStats= {
        call = function()
            local sys = require "luci.sys"
            local res
            local cmd
            cmd="bt.sh bt_get_serial_stats"
            res=luci.sys.exec(cmd)
            return {results = json.parse(res)}
        end
    },

    getCertificateNames= {
	call = function()	
		local certs =luci.sys.exec("/usr/sbin/certprint.sh credentials 2>/dev/null")
		local res={}
		for str in string.gmatch(certs, "[^\r\n]+") do
		       table.insert(res, str)
		end
		return {results = res }
	end
   },

    getrfcommConnect= {
        args = { master = "" , btaddress=""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd
            if args.btaddress then 
                cmd="bt.sh bt_rfcomm_master_connect " .. tostring(args.master) .. " " .. tostring(args.btaddress)
                res=luci.sys.exec(cmd)
                else
                res="Enter BT Address"
            end
            return {results = res}
        end
    },

    getrfcommDisconnect= {
        args = { master = "" , btaddress=""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd 
            if args.btaddress then 
                cmd="bt.sh bt_rfcomm_master_disconnect " .. tostring(args.btaddress) .. " " .. tostring(args.master)
                res=luci.sys.exec(cmd)
                else
                res="Enter BT Address"
            end
            return {results = res}
        end
    },

    getSlaveRfcommDisconnect= {
        args = {btaddress=""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd
            cmd="bt.sh bt_rfcomm_slave_disconnect " .. tostring(args.btaddress)
            res=luci.sys.exec(cmd)
            return {results = res}
        end
    },


    getPaired_Connected_Status= {
        call = function()
            local sys = require "luci.sys"
            local res=nil
            res=luci.sys.exec("bt.sh bt_paired_and_rfcomm_connected")
            return {results = json.parse(res)}
        end
    },

    getUnpairBluetooth= {
        args = { device = "" , btaddress="", masterno=""},
        call = function(args)
            local sys = require "luci.sys"
            local res=""
            local cmd 
            if args.btaddress then 
                cmd="bt.sh bt_unpair_device " .. tostring(args.btaddress) .. " " .. tostring(args.masterno)
                res=luci.sys.exec(cmd)
                else
                res="Enter BT Address"
            end
            return {results = res}
        end
    },

    getPairBluetooth= {
        args = { device = "" , btaddress=""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd 
            if args.btaddress then 
                cmd="bt.sh bt_pair_device " .. tostring(args.btaddress)
                res=luci.sys.exec(cmd)
                else
                res="Enter BT Address"
            end
            return {results = res}
        end
    },

    getPairStatusBluetooth= {
        args = { device = "" , btaddress=""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd 
            if args.btaddress then 
                cmd="bt.sh bt_device_paired_status " .. tostring(args.btaddress)
                res=luci.sys.exec(cmd)
                else
                res="Enter BT Address"
            end
            return {results = res}
        end
    },

    getBtScanDevices= {
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_manual_scan"
            res=luci.sys.exec(cmd)
            return {results = res}
        end
    },

    getBtScanDevicesOn= {
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_manual_scan_on"
            res=luci.sys.exec(cmd)
            return {results = res}
        end
    },

    getBtScanDevicesOff= {
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_manual_scan_off"
            res=luci.sys.exec(cmd)
            return {results = res}
        end
    },

    getBtScanResults={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res=nil, maindata
            maindata=luci.sys.exec("bt.sh bt_scan_results")
            --luci.sys.exec("echo %q > /tmp/rohan123" % maindata)
            res=json.parse(maindata)
            return {results = res}
        end
    },

    setBtInit={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_init " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    getBtState={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_state " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    setBtTurnOn={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_on " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    setBtTurnOff={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_off " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    getBtName={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_name_read " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    setBtName={
        args = { device = "", name = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_name_change " .. args.device .. " " .. args.name
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    getBtAddress={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res
            local cmd="bt.sh bt_addr_read " .. args.device 
            res=luci.sys.exec(cmd)
            return { results = res }
        end
    },

    getBtPairedDevices={
        args = { device = ""},
        call = function(args)
            local sys = require "luci.sys"
            local res = {}
            local cmd="bt.sh bt_paired_devs " .. args.device
            local data=luci.sys.exec(cmd)
            for token in string.gmatch(data, "[^\n]+") do
                tmp = token:match("(%w+:%w+:%w+:%w+:%w+:%w+ )")
                val=token:gsub( tmp,"")
                tmp=tmp:gsub(" ","")
                table.insert(res,tmp)
                table.insert(res,val)
            end
            return { results = res }
        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 pass" }))
        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 vikas" }))
            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
