local cgi = require("luamods/cgi")
local layout = require("luamods/layout")
local command = require("luamods/command")
local db = require("luamods/db")
local rsm_conf = require("config/rsm_conf")
local gsmio_conf = require("config/gsmio_conf")
local io_parse = require("luamods/io_parse")

saved = 0

local escape_lua_pattern
do
    local matches =
    {
        ["^"] = "%^";
        ["$"] = "%$";
        ["("] = "%(";
        [")"] = "%)";
        ["%"] = "%%";
        ["."] = "%.";
        ["["] = "%[";
        ["]"] = "%]";
        ["*"] = "%*";
        ["+"] = "%+";
        ["-"] = "%-";
        ["?"] = "%?";
        ["\0"] = "%z";
    }

    escape_lua_pattern = function(s)
        return (s:gsub(".", matches))
    end
end

typeStrings = {}
typeStrings["00"] = "IO"
typeStrings["01"] = "AC"
typeStrings["02"] = "ANALOG"
typeStrings["03"] = "ANALOG_IO"
typeStrings["04"] = "SNMP"
typeStrings["05"] = "MODBUS"
typeStrings["06"] = "DLMS"
typeStrings["07"] = "VEEDER_ROOT"
typeStrings["08"] = "CAMERA"
typeStrings["09"] = "OTHER"
typeStrings["0A"] = "UNKNOWN"

header = layout.getHeader()
footer = layout.getFooter()

userLevel = db.getPriv(layout.username) or 1

if (userLevel == 1) then
    buttonControl = " disabled"
    inputControl = " readonly"
    scriptControl = "//"
else
    buttonControl = ""
    inputControl = ""
    scriptControl = ""
end

id = cgi.post.id or ""
if (id ~= "") then
    edit = 1
else
    edit = 0
end

gsmconfig = command.ex([[cat ]]..gsmio_conf.iodriver_gsm_xml) or ""

gsmlabels = {}
if (gsmconfig ~= "") then
    for label in gsmconfig:gmatch([[<Label%s+name=%"(.-)%".->]]) do
        table.insert(gsmlabels, label)
    end
end

rule = {}
rule.matched = 0
rule.inputs = {}
rule.output = {}

if (cgi.post.saveButton == "Save and Apply") and (userLevel ~= 1) then
    ioconfig = command.ex([[cat ]]..gsmio_conf.iodriver_xml) or ""
    
    for count = 1,10 do
      if (cgi.post["input" .. count] ~= nil) and cgi.post["input" .. count] ~= "" then
        tmprule = {}
        tmprule.label, tmprule.type = cgi.post["input" .. count]:match("%('(.-)','(.-)'%)")      
        
        if (cgi.post["invert_in" .. count] == "invert") then
            tmprule.invert = "true"
        else
            tmprule.invert = "false"
        end
        
        if (tmprule.label ~= nil) and (tmprule.type ~= nil) then
            table.insert(rule.inputs, tmprule)
        end
      end
    end
    
    if (cgi.post.output ~= "") then
        rule.output.label, rule.output.type = cgi.post.output:match("%('(.-)','(.-)'%)")
    end
    if (cgi.post["invert_out"] == "invert") then
        rule.operation = "INVERSE"
    else
        rule.operation = ""
    end
    
    if (#(rule.inputs) > 0) and (rule.output.label ~= nil) then
        newXML = [[
<connection id="]]..id..[[">
]]
  if (cgi.post.operation:match("AND")) then
    newXML = newXML .. [[    <trigger operation="AND">
]]
  elseif (cgi.post.operation:match("OR")) then
    newXML = newXML .. [[    <trigger operation="OR">
]]
  end
        for idx, input in ipairs(rule.inputs) do
            newXML = newXML .. [[
        <detail dev_type="]]..input.type..[[" io_label="]]..input.label..[[" io_invert="]]..input.invert..[["/>
]]
        end
        newXML = newXML .. [[
    </trigger>
]]
        if (rule.operation == "INVERSE") then
            newXML = newXML .. [[
    <action operation="INVERSE">
]]
        else
            newXML = newXML .. [[
    <action>
]]
        end
        newXML = newXML .. [[
        <detail dev_type="]]..rule.output.type..[[" io_label="]]..rule.output.label..[["/>
    </action>
</connection>]]
        if (ioconfig:match([[<connection id="]]..id..[[">]])) then
            newconfig = ioconfig:gsub([[<connection id="]]..id..[[">.-</connection>]],newXML)
        else
            newconfig = ioconfig:gsub("</io_connections>",newXML.."\n</io_connections>")
        end
        command.ex("sv stop gsmiodriver")
        command.writefile(gsmio_conf.iodriver_xml, newconfig)
        --not used anymore
        --io_parse.parseToFinalXML()
        command.ex("sv start gsmiodriver")
        saved = 1
        edit = 1
    end
end

if (cgi.post.deleteButton == "Delete Rule") and (userLevel ~= 1) then
    ioconfig = command.ex([[cat ]]..gsmio_conf.iodriver_xml) or ""
    tmpcon = ioconfig:match([[%s-<connection id="]]..id..[[">.-</connection>%s-]]) or ""
    if (tmpcon ~= "") then
        newconfig = ioconfig:gsub(escape_lua_pattern(tmpcon), "")
        command.writefile(gsmio_conf.iodriver_xml, newconfig)
        
        content = [[
                    <div id="info">
                        <div style="background:url(images/iodriver.png); background-size:32px; background-repeat:no-repeat; background-position: 20px center;">
                            <center><h1>Edit IO Logic Rule</h1></center>
                        </div>
                    </div>
                    <div id="info">
                        <center>
                            <h2>Logic Rule Deleted</h2>
                            <b>The rule has been deleted...</b><br><br>
                            <A HREF="io_logic.lua">Back to IO Logic</A>
                        </center>
                    </div>
]]
        print(header..content..footer)
        os.exit()        
    end
end

-- Reset them again
rule = {}
rule.matched = 0
rule.inputs = {}
rule.output = {}

lastid = 0
ioconfig = command.ex([[cat ]]..gsmio_conf.iodriver_xml) or ""
for tmpid, concfg in ioconfig:gmatch([[<connection%s+id="(.-)">%s-(.-)%s-</connection>]]) do
    if (tonumber(tmpid) > lastid) then
        lastid = tonumber(tmpid)
    end
    if (id == tmpid) then
        rule.matched = 1
        
        operation, triggercfg = concfg:match("<trigger%s-(.-)%s->(.-)</trigger>")
        if (operation ~= nil) then
            if operation:match([[operation="AND"]]) then
                rule.operation_trigger = "AND"
            elseif operation:match([[operation="OR"]]) then
                rule.operation_trigger = "OR"
            end
        end
        for inputs in triggercfg:gmatch("<detail.-/>") do
            input={}
            input.devType = inputs:match([[dev_type="(.-)"]]) or ""
            input.label = inputs:match([[io_label="(.-)"]]) or ""
            input.invert = inputs:match([[io_invert="(.-)"]]) or "false"
            table.insert(rule.inputs, input)
        end
        
        operation, actioncfg = concfg:match("<action%s-(.-)%s->(.-)</action>")
        if (operation ~= nil) then
            if operation:match([[operation="INVERSE"]]) then
                rule.operation = "INVERSE"
            else
                rule.operation = ""
            end
        end
        if (actioncfg ~= nil) then
            outputcfg = actioncfg:match("<detail.-/>") or ""
            if (outputcfg ~= "") then
                rule.output.devType = outputcfg:match([[dev_type="(.-)"]]) or ""
                rule.output.label = outputcfg:match([[io_label="(.-)"]]) or ""
            end
        end
    end
end

if (id == "") then 
    id = lastid + 1
end

if (edit == 1) and (rule.matched == 0) then
    content = [[
                    <div id="info">
                        <div style="background:url(images/iodriver.png); background-size:32px; background-repeat:no-repeat; background-position: 20px center;">
                            <center><h1>Edit IO Logic Rule</h1></center>
                        </div>
                    </div>
                    <div id="info">
                        <center>
                            <h2><img src="images/warning.png"/> Invalid Rule ID</h2>
                            <b>An invalid rule ID was specified.</b><br><br>
                            <A HREF="io_logic.lua">Back to IO Logic</A>
                        </center>
                    </div>
]]
    print(header..content..footer)
    os.exit()
end

inputs = {}
outputs = {}
analoginputs={}

response = command.ex(rsm_conf.rsmc_path.." GET: TAG_MSG_INFO TAG_MSG_INFO_IDX_ONLY TAG_DEV_CFG") or ""
devices = {}
if (response ~= "") then
    for id in response:gmatch("TAG_DEV_CFG%s+TAG_DEV_ID=(%x+)%s-") do
        devCfg = command.ex(rsm_conf.rsmc_path.." GET: TAG_DEV_CFG TAG_DEV_ID="..id)
        if (devCfg ~= nil) then
            device = {}
            device.id = id
            device.label = devCfg:match([[TAG_DEV_LABEL=%"(.-)%"]]) or "unknown"
            device.inputs = {}
            device.outputs = {}
            device.analogs = {}
            device.type = devCfg:match([[TAG_DEV_TYPE=(%x+)]])
            devCfg = command.ex(rsm_conf.rsmc_path.." GET: TAG_IP_CFG TAG_DEV_ID="..id)
            if (devCfg ~= nil) then
                for inputCfg in devCfg:gmatch("TAG_IP_CFG%s+(.-)%s+TAG_IO_TYPE=01") do
                    input = {}
                    input.devID = id
                    input.pnum = string.format("%02d", tonumber(inputCfg:match("TAG_IO_PNUM=(%x+)"),16))
                    input.label = inputCfg:match([[TAG_IO_LABEL=%"(.-)%"]]) or "unknown"
                    table.insert(device.inputs, input)
                end
            end
            devCfg = command.ex(rsm_conf.rsmc_path.." GET: TAG_OP_CFG TAG_DEV_ID="..id)
            if (devCfg ~= nil) then
                for outputCfg in devCfg:gmatch("TAG_OP_CFG%s+(.-)%s+TAG_IO_TYPE=02") do
                    output = {}
                    output.devID = id
                    output.pnum = string.format("%02d", tonumber(outputCfg:match("TAG_IO_PNUM=(%x+)"),16))
                    output.label = outputCfg:match([[TAG_IO_LABEL=%"(.-)%"]]) or "unknown"
                    table.insert(device.outputs, output)
                end
            end
            devCfg = command.ex(rsm_conf.rsmc_path.." GET: TAG_AI_CFG TAG_DEV_ID="..id)
            if (devCfg ~= nil) then
                for outputCfg in devCfg:gmatch("TAG_AI_CFG%s+(.-)%s+TAG_IO_TYPE=03") do
                    analog = {}
                    analog.devID = id
                    analog.pnum = string.format("%02d", tonumber(outputCfg:match("TAG_IO_PNUM=(%x+)"),16))
                    analog.label = outputCfg:match([[TAG_IO_LABEL=%"(.-)%"]]) or "unknown"
                    table.insert(device.analogs, analog)
                end
            end
            table.insert(devices, device)
        end
    end
end

content = ""

content = content .. [[
                    <div id="info">
                        <div style="background:url(images/iodriver.png); background-size:32px; background-repeat:no-repeat; background-position: 20px center;">
]]
if (edit == 1) then
    content = content .. [[
                            <center><h1>Edit IO Logic Rule</h1></center>
]]
else
    content = content .. [[
                            <center><h1>Add New IO Logic Rule</h1></center>
]]
end
content = content .. [[
                        </div>
                    </div>
]]

if (userLevel == 1) then
    content = content .. [[
                    <center><b>Note:</b> Editing this section requires administrator privileges.</center><br>
]]
end

if (response == "") then
    content = content .. [[
                    <div id="info">
                        <center>
                            <h2><img src="images/warning.png"/> Invalid response</h2>
                            The RSM client ]]..rsm_conf.rsmc_path..[[ is missing, not responding or returned an invalid reply.<br><br>
                            Cannot confirm validity of connection I/Os.
                        </center>
                    </div> 
    ]]                    
end

defaultInputOptions = [[
                                            <option value='' selected>(none) Select Input</option>
]]
defaultOutputOptions = [[
                                            <option value='' selected>(none) Select Output</option>
]]

for idx, dev in ipairs(devices) do
    foundInputs = 0
    for idx = #(dev.inputs),1,-1 do
        if foundInputs == 0 then
            foundInputs = 1
            defaultInputOptions = defaultInputOptions..[[
                                            <optgroup label=']]..dev.id.." / "..dev.label..[['>
]]
        end
        defaultInputOptions = defaultInputOptions..[[
                                                <option value="(']]..dev.inputs[idx].label..[[',']]..typeStrings[dev.type]..[[')">]]..dev.inputs[idx].pnum.." / "..dev.inputs[idx].label..[[</option>
]]
    end
  for idx = #(dev.outputs),1,-1 do
        if foundInputs == 0 then
            foundInputs = 1
            defaultInputOptions = defaultInputOptions..[[
                                            <optgroup label=']]..dev.id.." / "..dev.label..[['>
]]
        end
        defaultInputOptions = defaultInputOptions..[[
                                                <option value="(']]..dev.outputs[idx].label..[[',']]..typeStrings[dev.type]..[[')">]]..dev.outputs[idx].pnum.." / "..dev.outputs[idx].label..[[</option>
]]
    end
  for idx = #(dev.analogs),1,-1 do
        if foundInputs == 0 then
            foundInputs = 1
            defaultInputOptions = defaultInputOptions..[[
                                            <optgroup label=']]..dev.id.." / "..dev.label..[['>
]]
        end
        defaultInputOptions = defaultInputOptions..[[
                                                <option value="(']]..dev.analogs[idx].label..[[',']]..typeStrings[dev.type]..[[')">]]..dev.analogs[idx].pnum.." / "..dev.analogs[idx].label..[[</option>
]]
    end
    
    if (foundInputs == 1) then
        defaultInputOptions = defaultInputOptions..[[
                                            </optgroup>
]]
    end
    
    foundOutputs = 0
    for idx = #(dev.outputs),1,-1 do
        if foundOutputs == 0 then
            foundOutputs = 1
            defaultOutputOptions = defaultOutputOptions..[[
                                            <optgroup label=']]..dev.id.." / "..dev.label..[['>
]]
        end
        defaultOutputOptions = defaultOutputOptions..[[
                                                <option value="(']]..dev.outputs[idx].label..[[',']]..typeStrings[dev.type]..[[')">]]..dev.outputs[idx].pnum.." / "..dev.outputs[idx].label..[[</option>
]]
    end
    if (foundOutputs == 1) then
        defaultOutputOptions = defaultOutputOptions..[[
                                            </optgroup>
]]
    end
end

if (#(gsmlabels) > 0) then
    defaultInputOptions = defaultInputOptions .. [[
                                            <optgroup label="GSM Inputs">
]]
    for i, lab in ipairs(gsmlabels) do
        defaultInputOptions = defaultInputOptions.. [[
                                                <option value="(']]..lab..[[','GSM')">]]..lab..[[</option>
]]            
    end
    defaultInputOptions = defaultInputOptions .. [[
                                            </optgroup>
]]
    defaultOutputOptions = defaultOutputOptions .. [[
                                            <optgroup label="GSM Outputs">
]]
    for i, lab in ipairs(gsmlabels) do
        defaultOutputOptions = defaultOutputOptions.. [[
                                                <option value="(']]..lab..[[','GSM')">]]..lab..[[</option>
]]            
    end
    defaultOutputOptions = defaultOutputOptions .. [[
                                            </optgroup>
]]
end

inputOptions = defaultInputOptions
outputOptions = defaultOutputOptions

content = content .. [[
                    <script>
                        var doValidate = 0;
                        function validateForm(form)
                        {
                            if (form.getAttribute('submitted')) return false;
                            
                            if (!doValidate)
                            {
                                form.setAttribute('submitted','true');
                                return true;
                            }
                            doValidate = 0;
                            
                            var errors = 0;
                            if (form.output.value == "")
                            {
                                alert("Please select a valid output action.");
                                return false;
                                
                            }
                            
                            if ((form.input1.value == "") && (form.input2.value == "") && (form.input3.value == ""))
                            {
                                alert("Please select at least one valid input.");
                                return false;
                            }
                            
                            form.setAttribute('submitted','true');
                            return true;
                        }
                    
                    
                        //Add more fields dynamically.
                        function addField(field, limit)
                        {
                            if (!document.getElementById) return; //Prevent older browsers from getting any further.
                            var field_area = document.getElementById(field+"_list");
                            var all_inputs = field_area.getElementsByTagName("select"); //Get all the input fields in the given area.
                            var count = all_inputs.length;
                            if(count+1 > limit && limit > 0) return;
                            
                            if(document.createElement)
                            { //W3C Dom method.
                                var li = document.createElement("li");
                                li.innerHTML =
                                     "<a style=\"cursor:pointer;color:blue;\" onclick=\"removeField(this, '"+field+"');\"> <img src=\"images/trash.png\" alt=\"Delete\" title=\"Delete\"/></a> " 
                                    +"<select name=\"input"+(count+1)+"\" style=\"width: 180px\">"
                                        +"<option value=\"('0','Select Input')\">Save To Populate</option>"
                                    +"</select> "
                                    +"<a style=\"cursor:pointer;color:blue;\" onclick=\"invertInput(\"invert_in"+ (count+1) + "\");\"> <img id=\"invert_in" + (count+1) + "_img\" src=\"images/normal.png\" style=\"vertical-align: middle;\"  height=\"20\" width=\"20\"/></a>"
                                    +"<input type=\"hidden\" id=\"invert_in" +  (count+1) + "\" name=\"invert_in" + (count+1) + "\" value=\"normal\"/>"
                                field_area.appendChild(li);
                            }
                            else
                            {       //Older Method
                            }
                        }
                        
                        //Remove fields dynamically
                        function removeField(node,field)
                        {
                            node.parentNode.parentNode.removeChild(node.parentNode);
                            var field_area = document.getElementById(field+"_list");
                            var all_inputs = field_area.getElementsByTagName("input"); //Get all the input fields in the given area.
                            var all_selects = field_area.getElementsByTagName("select"); //Get all the input fields in the given area.
                            var loop;
                            for (loop = 0; loop < all_inputs.length; loop++)
                            {
                                all_inputs[loop].name = "invert_in"+((loop)+1);
                            }
                            for (loop = 0; loop < all_selects.length; loop++)
                            {
                                all_selects[loop].name = "input"+(loop+1);
                            }
                        }
                        
                        function rotateImg(img_name,doRotate)
                        {
                            if (!document.getElementById) return; //Prevent older browsers from getting any further.
                        
                            var currentImgObj = document.getElementById("and_or_img");
                            if (!currentImgObj) return;
                            var currentImgValue = document.getElementById('and_or_img').getAttribute('name');
                            var hidden_op = document.getElementById('io_op');
                            if (doRotate)
                            {
                              if (hidden_op.value == 'AND')
                              {
                                currentImgObj.src = "images/or.png";
                                hidden_op.setAttribute('value','OR');
                              }
                              else if (hidden_op.value == 'OR')
                              {
                                currentImgObj.src = "images/and.png";
                                hidden_op.setAttribute('value','AND');
                              }
                            }
                        }
                        
                        function invertInput(input_name)
                        {
                            if (!document.getElementById) return; //Prevent older browsers from getting any further.
                        
                            var currentImgObj = document.getElementById(input_name+'_img');
                            if (!currentImgObj) return;
                            var hidden_op = document.getElementById(input_name);
                            
                            
                            if (hidden_op.value == 'normal')
                            {
                              currentImgObj.setAttribute('src',"images/not.png");
                              hidden_op.setAttribute('value','invert');
                            }
                            else if (hidden_op.value == 'invert')
                            {
                              currentImgObj.setAttribute('src',"images/normal.png");
                              hidden_op.setAttribute('value','normal');
                            }
                        }
                    </script>
    
                    <div class="formLayoutfull">
                        <b>Select at least one input to trigger an output action.</b><br><br>
                        <b> Note: Click on the images to toggle inversion of input/ouput and to select AND/OR operation </b><br><br>

                        <form action="io_logic_edit.lua" method="post" onsubmit="return validateForm(this);">
                            <table style="border: 0;">
                            <tr style="border: 0;">
                                <th style="border: 0;" width="40%" valign="middle" align="right">Inputs</th>
                                <th style="border: 0;" width="20%" valign="middle" align="center">Operation</th>
                                <th style="border: 0;" width="40%" valign="middle" align="left">Output</th>
                            </tr>
                                <tr>
                                
                            <td valign="middle" align="right">
                            <div id="input_div">
                            <ul id="input_list" style="list-style-type: none;">

]]

    if (#(rule.inputs) > 0) then
        for i = 1, #(rule.inputs)  do
            if (i > 0) then
                content = content .. [[<li>
                                        <a style="cursor:pointer;color:blue;" onclick="removeField(this, 'input');"> <img src="images/trash.png" alt="Delete" title="Delete"/></a>
                                        <select name="input]] .. i .. [[" style="width: 180px">
]]
                inputSelect = inputOptions:match([[(<option value="%(']]..rule.inputs[i].label..[[','.-'%)">.-</option>)]])
                if (inputSelect) then
                    newi = inputSelect:gsub([[">]], [[" selected>]])
                    inputOptions = inputOptions:gsub(escape_lua_pattern(inputSelect), newi)
                end
                content = content .. inputOptions
                inputOptions = defaultInputOptions
                content = content .. [[    
                                                        </select>]]                                                   

                if (rule.inputs[i].invert == "true") then
                content = content .. [[    <a style="cursor:pointer;color:blue;" onclick="invertInput('invert_in]] .. i .. [[');"> <img id="invert_in]] .. i .. [[_img" src="images/not.png" style="vertical-align: middle;"  height="20" width="20"/></a>
                                           <input type="hidden" id="invert_in]] .. i .. [[" name="invert_in]] .. i .. [[" value="invert"/>
]]
                else
                content = content .. [[    <a style="cursor:pointer;color:blue;" onclick="invertInput('invert_in]] .. i .. [[');"> <img id="invert_in]] .. i .. [[_img" src="images/normal.png" style="vertical-align: middle;"  height="20" width="20"/></a>
                                           <input type="hidden" id="invert_in]] .. i .. [[" name="invert_in]] .. i .. [[" value="normal"/>
]]                
                
                end
                content = content ..  [[
                                      </li>
]]                                      
            end
        end
    else
                content = content .. [[<li>
                                        <a style="cursor:pointer;color:blue;" onclick="removeField(this, 'input');"> <img src="images/trash.png" alt="Delete" title="Delete"/></a>
                                        <select name="input]] .. 1 .. [[" style="width: 180px">
]]

                inputOptions = defaultInputOptions
                content = content .. inputOptions .. [[    
                                                        </select>]]                                                   

                  content = content .. [[
                                                          <input type="checkbox" name="invert_in]] .. 1 .. [[">Invert input</input>
]]

                content = content ..  [[
                                      </li>
]]     
    end
                       
content = content .. [[     </ul>
                            </div> 
                            </td>                   
                                    <td align="center" valign="middle" >
]]
if (rule.operation_trigger == "OR") then
    content = content .. [[
    <a style="cursor:pointer;color:blue;" onclick="rotateImg('and_or_img',1);" align="center"> <img id="and_or_img" name="OR" value="OR" src="images/or.png" style="vertical-align: middle;" height="70" width="82"/></a>
    <input type="hidden" id="io_op" name="operation" value="OR"/>
]]
else
    content = content .. [[
    <a style="cursor:pointer;color:blue;" onclick="rotateImg('and_or_img',1);" align="center"> <img id="and_or_img" name="AND" value="AND" src="images/and.png" style="vertical-align: middle;" height="70" width="82"/></a>
    <input type="hidden" id="io_op" name="operation" value="AND"/>
]]
end

content = content ..    [[ </td>
                           <td valign="middle" align="left">
]]

if (rule.operation == "INVERSE") then
                content = content .. [[    <a style="cursor:pointer;color:blue;" onclick="invertInput('invert_out');"> <img id="invert_out_img" src="images/not.png" style="vertical-align: middle;"  height="20" width="20"/></a>
                                           <input type="hidden" id="invert_out" name="invert_out" value="invert"/>
]]
                else
                content = content .. [[    <a style="cursor:pointer;color:blue;" onclick="invertInput('invert_out');"> <img id="invert_out_img" src="images/normal.png" style="vertical-align: middle;"  height="20" width="20"/></a>
                                           <input type="hidden" id="invert_out" name="invert_out" value="normal"/>
]]
end

content = content ..    [[            
                                        <select name="output">
]]

if (rule.matched == 1) then
    o = outputOptions:match([[(<option value="%(']]..rule.output.label..[[','.-'%)">.-</option>)]])
    if (o) then
        newo = o:gsub([[">]], [[" selected>]])
        outputOptions = outputOptions:gsub(escape_lua_pattern(o), newo)
    end
end    

content = content .. outputOptions
outputOptions = defaultOutputOptions
content = content .. [[    

                                        </select>
]]
content = content .. [[
                                    </td>
                                </tr>
                            </table>
                            <br>

                            <table style="border: 0;" width="100%">
                            <tr valign="middle">
                            <td width="50%"> <input type="button" row-span="2" value="Add Input" onclick="addField('input', 10);"]]..buttonControl..[[/> </td>

                            <td width="50%"  align="right"> <b> Not Inverted: <img src="images/normal.png" style="vertical-align: middle;"  height="20" width="20"/> </td>
                            </tr>
                            <tr valign="middle">
                             <td> </td>
                             <td width="50%"  align="right"> <b> Inverted:     <img src="images/not.png" style="vertical-align: middle;"  height="20" width="20"/> </td>
                            </tr>
                            </table>
]]                            
if (saved == 1) then
        content = content .. [[
                            <b><img src="images/ok.png"/> Changes saved.</b><br><br>
]]
end                            
    content = content .. [[
                            <input type="hidden" name="id" value="]]..id..[["/>
                            <input type="button" value="Back to Logic" onclick="window.location.assign('io_logic.lua');"/>
                            <input type="submit" value="Save and Apply" name="saveButton"]]..buttonControl..[[ onclick="doValidate = 1;"/>
]]
if (edit == 1) then
    content = content .. [[
                            <input type="submit" value="Delete Rule" name="deleteButton"]]..buttonControl..[[ onclick="return confirm('Are you sure you want to delete this IO rule?');"/>
]]
end
content = content .. [[
                        </form>
                    </div>
]]                        


html = header
html = html..content
html = html..footer

print(html)
