require("rsmdict")
require("rsm_serials")

--The Objects that is supported by the Script
local obj_ids = {
                   RSM.RSM_TagID.TAG_BUS_SNMP                    
                }
                
local snmp = {}
local snmp_file = ""
local snmp_conf_file="/etc/rsm/sddconf.xml"
local snmp_conf_file_test="/usr/share/lua/kses/test_bus_snmp.xml"
local newSerialnum = ""
local newFile = ""
local sdd_down = "/usr/bin/sv down sdd"
local sdd_up = "/usr/bin/sv up sdd"

local snmpFiles = {}
local templateFiles = {}
local snmpPath = ""
local templatePath = ""

function print_table(t,p)

   for k,v in pairs(t) do
     print(p,k,v)
     if(type(v)=="table") then 
         print_table(v,p.."\t")
     end
  end
end


--Retuen the Object List
function getObjects()
 return obj_ids;
end

--Convert the config file into an object message nd return that.
--Actually supposed to check the request object to find the exact object if any to 
--return. We jippo that by always returning all of them
function getConfig(cfg)
  load_snmp()
  msg = snmp_to_msg()
  return msg
end


--Function to lookup and set a specific object(s)
--and then to update the cofig file with those values
function setConfig(cfg)
   load_snmp()   
   update_snmp(cfg)
   store_snmp()
end

function deleteConfig(cfg)
   load_snmp()
   delete_snmp(cfg)
end

function replaceConfig(cfg)
   
end


function command_exec(cmd)
  local f = io.popen(cmd) 
  value = f:read("*a") or "none"
  f:close()
  return value
end

function scandir(directory)
  local i, t, popen = 0, {}, io.popen
    for filename in popen('ls -a "'..directory..'"'):lines() do
        i = i + 1
        t[i] = filename
    end
    return t
end

function writefile(fileaddres,value)
  local f = io.open(fileaddres,"w+")
  f:write(value)
  f:close()
  return true
end

function load_snmp() 
  --print("Loading pf data...") 
  snmp = {}
  
  snmpConfig = command_exec("cat "..snmp_conf_file)
  snmpFiles = {}
  templateFiles = {}
  if (snmpConfig ~= 0) then
    snmpPath = snmpConfig:match('<path%s+name=%"devices%"%s->(.-)</path>') or ""    
    if (snmpPath ~= "") then
      snmpFiles = scandir(snmpPath)
      table.remove(snmpFiles,1)
      table.remove(snmpFiles,1)
    end
    templatePath = snmpConfig:match('<path%s+name=%"templates%"%s->(.-)</path>') or ""    
    if (templatePath ~= "") then
      templateFiles = scandir(templatePath)
      table.remove(templateFiles,1)
      table.remove(templateFiles,1)
    end
  end
  
--[[print("List of SNMP devices:")
print_table(snmpFiles,0)
print("List of SNMP templates:")
print_table(templateFiles,0)]]--

if(snmpFiles ~= 0) then
  for idx, snmpFile in pairs(snmpFiles) do
    cfg = command_exec("cat "..snmpPath .. "/" .. snmpFile)
    
    if (cfg:match("<device>(.+)</device>") == nil) then
      print("The following SNMP file is empty: " .. snmpFile)
    else
      snmp[snmpFile] = {}      
      snmp[snmpFile].serialnum = cfg:match([[<serial>%s-(.-)%s-</serial>]]) or "unknown"
      snmp[snmpFile].label = cfg:match("<label>%s-(.-)%s-</label>") or "unknown"
      snmp[snmpFile].template = cfg:match("<template>%s-(.-)%s-</template>") or "unknown"
      snmp[snmpFile].host = cfg:match("<host>%s-(.-)%s-</host>") or "unknown"
      snmp[snmpFile].community = cfg:match("<community>%s-(.-)%s-</community>") or "unknown"
      snmp[snmpFile].version = cfg:match("<version>%s-(.-)%s-</version>") or "2c"
    end
    
    
    
  end    
end

              
end

function snmp_to_msg()
  local msg = {}
  snmp_ctr = 0
  
  --print("Load Message: ")
  --Send Subnet info
  for idx,sff in pairs(snmp) do
     snmp_cfg = {}
     snmp_cfg.objid =  RSM.RSM_TagID.TAG_BUS_SNMP
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_SERIALNUM] = sff.serialnum              
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_LABEL] = sff.label
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_TEMPLATE] = sff.template
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_HOST] = sff.host
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_COMMUNITY] = sff.community
     snmp_cfg[RSM.RSM_TagID.TAG_BUS_VERSION] = sff.version
     
          
     msg[snmp_ctr] = snmp_cfg
     snmp_ctr = snmp_ctr+1
  end  
  
  return msg
end

function update_snmp(cfg)
   for idx,obj in pairs(cfg) do      
      if obj.objid and obj.objid == RSM.RSM_TagID.TAG_BUS_SNMP then                    
          if obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] ~= '' then
              print("Incoming Serial nunmber: "..obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM])        
              obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] = obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] .. ".xml"                  
              sf = snmp[obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM]]              
              --print("Adding object: " .. obj[RSM.RSM_TagID.TAG_NET_LABEL]);
              if sf then
                setsnmp(sf,obj)
              end
          else
              print("Recognised new snmp...")             
              newSerialnum = generateNewSerial()              
              newFile = newSerialnum..".xml"
              snmp[newFile] = {}
              sf = snmp[newFile]              
              if sf then
                sf.serialnum = newSerialnum                
                setsnmp(sf,obj)
              end
          end 
      end      
   end 
end


function setsnmp(sf,obj)
    
    if obj[RSM.RSM_TagID.TAG_BUS_LABEL] then
       sf.label = obj[RSM.RSM_TagID.TAG_BUS_LABEL]
    end
    if obj[RSM.RSM_TagID.TAG_BUS_TEMPLATE] then
       sf.template = obj[RSM.RSM_TagID.TAG_BUS_TEMPLATE]
    end
    if obj[RSM.RSM_TagID.TAG_BUS_HOST] then
       sf.host = obj[RSM.RSM_TagID.TAG_BUS_HOST]
    end
    if obj[RSM.RSM_TagID.TAG_BUS_COMMUNITY] then
       sf.community = obj[RSM.RSM_TagID.TAG_BUS_COMMUNITY]
    end
    if obj[RSM.RSM_TagID.TAG_BUS_VERSION] then
       sf.version = obj[RSM.RSM_TagID.TAG_BUS_VERSION]
    end
     
    sf.changed = 1
    
end



function store_snmp()

  for idx,sf in pairs(snmp) do
         if sf.changed and sf.changed == 1 then
            newXML = [[
<!-- ]]..snmpPath..[[/]]..sf.serialnum..[[.xml generated by webconfig -->
<device>
    <label>]]..sf.label..[[</label>
    <serial>]]..sf.serialnum..[[</serial>
    <template>]]..sf.template..[[</template>
    <community>]]..sf.community..[[</community>
    <network>
        <host>]]..sf.host..[[</host>
    </network>
    <version>]]..sf.version..[[</version>
</device>
<!-- end of file -->
]]

            command_exec(sdd_down)
            writefile(snmpPath..[[/]]..sf.serialnum..[[.xml]],newXML)
            command_exec(sdd_up)
         end       
  end     
  
end


function delete_snmp(cfg)
   for idx,obj in pairs(cfg) do      
      if obj.objid and obj.objid == RSM.RSM_TagID.TAG_BUS_SNMP then                    
          if obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] ~= '' then
              print("Incoming Serial nunmber: "..obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM])        
              obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] = obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] .. ".xml"                  
              sf = snmp[obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM]]              
              --print("Adding object: " .. obj[RSM.RSM_TagID.TAG_NET_LABEL]);
              if sf then
                delsnmp(sf,obj)
              end
          else
              print("Error: No serial nmber provided to delete!")
          end 
      end      
   end 
end

function delsnmp(sf,obj)
    command_exec(sdd_down)
    command_exec("rm "..snmpPath..[[/]]..sf.serialnum..[[.xml]])
    command_exec(sdd_up)
end

--Testing....

--[[print("Testing...")
--print("Get Config: ")

print_table(getConfig(),0)

local testCfg = {}
local obj ={}
local obj1 ={}

obj.objid = RSM.RSM_TagID.TAG_BUS_SNMP
obj[RSM.RSM_TagID.TAG_BUS_SERIALNUM] = "0x7FA41A01"     
obj[RSM.RSM_TagID.TAG_BUS_LABEL] = "Test SNMPpppp"
obj[RSM.RSM_TagID.TAG_BUS_TEMPLATE] = "RECT_eaton_sc200.xml"
obj[RSM.RSM_TagID.TAG_BUS_HOST] = "10.15.3.20"
obj[RSM.RSM_TagID.TAG_BUS_COMMUNITY] = "public"
obj[RSM.RSM_TagID.TAG_BUS_VERSION] = "2c"


obj1.objid = RSM.RSM_TagID.TAG_BUS_SNMP
--obj1[RSM.RSM_TagID.TAG_BUS_SERIALNUM] = ""     
obj1[RSM.RSM_TagID.TAG_BUS_LABEL] = "test new snmp"
obj1[RSM.RSM_TagID.TAG_BUS_TEMPLATE] = "psc3.xml"
obj1[RSM.RSM_TagID.TAG_BUS_HOST] = "10.15.3.20"
obj1[RSM.RSM_TagID.TAG_BUS_COMMUNITY] = "public"
obj1[RSM.RSM_TagID.TAG_BUS_VERSION] = "2c"

testCfg[0] = obj
--testCfg[1] = obj1

setConfig(testCfg)
print_table(getConfig(),0)]]--





























