require("luamods/command")
require("luamods/layout")
require("luamods/cgi")
require("config/network_conf")

userLevel = db.getPriv(layout.username) or 1
if (userLevel == 1) then
    buttonControl = " disabled"
    inputControl = " readonly"
    scriptControl = "//"
else
    buttonControl = ""
    inputControl = ""
    scriptControl = ""
end

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

if (cgi.post.submitButton == "Save and Apply") and (userLevel ~= 1) then
    intfName = cgi.post.interface or "unknown"
    saved = 1
else
    intfName = cgi.get.interface or "unknown"
end

local function msg(m)
  command.ex([[echo "]]..m..[[" >> /var/log/lighttpd_cgi.log]])
end
currIntf = command.ex("cat "..network_conf.netctl_profile_path.."/"..intfName)

if (currIntf ~= nil) then
    --ifconfigResult = command.ex(network_conf.if_config.." "..intfName.." 2>&1") or ""
    interface = {}
    nameservers = {}
     method = currIntf:match("[^#]IP=(.-)\n") or "none"
     interface.name = intfName
     interface.method = method
     type = currIntf:match("[^#]Connection=(.-)\n") or "ethernet"
     interface.type = type
     address = currIntf:match("[^#]Address=%('(.+)/(.+)'%)\n") or ""
     netmask = currIntf:match("[^#]Address=%('.+/(.-)'%)\n") or ""
     gateway = currIntf:match("[^#]Gateway='(.-)'\n") or ""
     
     dns = currIntf:match("[^#]DNS=%((.-)%)\n") or currIntf:match("[^#]DNS=%('(.-)'%)\n") or ""
     for i in dns:gmatch("%S+") do
      value = i:gsub("%'", "") or nil
      if value ~= nil then
        table.insert(nameservers, value)
      end
     end
     
     search = currIntf:match("[^#]Domain=%('(.-)'%)\n") or nil
     if search ~= nil then
      searchList = search
     end
     
     if searchList == nil then searchList = "" end
     
     interface.address = address
     interface.netmask = netmask
     interface.gateway = gateway
     interface.dns = dns
     interface.domain = searchList
     
     interface.enabled = command.ex("netctl is-enabled "..interface.name):match("(enabled)") or ""
     interface.interface = currIntf:match("[^#]Interface=(.-)\n") or ""
     
     if interface.type == "wwan" then
        interface.apn = currIntf:match("[^#]AccessPointName=(.-)\n") or ""
        interface.user = currIntf:match("[^#]User=['\"]*(.-)['\"]*\n") or ""
        interface.password = currIntf:match("[^#]Password=['\"]*(.-)['\"]*\n") or ""
     end
 

    if (saved == 1) then
        newAddress = cgi.post.address or ""
        newNetmask = cgi.post.netmask or ""
        newGateway = cgi.post.gateway or ""
        newSearch = cgi.post.search or ""
        
        if (cgi.post.method == "dhcp") then
            newMethod = "dhcp"
        else
            newMethod = "static"
        end
        if (cgi.post.profile == "enabled") then
            newEnabled = "enabled"
        else
            newEnabled = ""
        end
        
       if newAddress ~= interface.address or newNetmask ~= interface.netmask then
          currIntf = currIntf:gsub("#Address","Address")
          currIntf = currIntf:gsub("Address=.-\n","Address=('"..newAddress.."/"..newNetmask.."')\n")   
       end

      if newMethod ~= interface.method then
          currIntf = currIntf:gsub("IP=.-\n","IP="..newMethod.."\n")
      end 
      
      if newGateway ~= interface.gateway then
         currIntf = currIntf:gsub("#Gateway","Gateway")
         if newGateway ~= "" then
            currIntf = currIntf:gsub("Gateway=.-\n","Gateway='"..newGateway.."'\n")
         else
            currIntf = currIntf:gsub("Gateway=.-\n","#Gateway=\n")
         end
      end
      
      
      -- Add NameServers to file
      newNameServers = "" 
        
      for count = 1,10 do
        if (cgi.post["server"..count] ~= nil) then
            ns = cgi.post["server"..count]
            if (ns ~= nil) and (ns ~= "") then
                newNameServers = newNameServers.."'"..ns.."' " 
            end
        end
      end
        
      
      if newNameServers ~= interface.dns then
        value1 = currIntf:match("[^#]DNS=%((.-)%)\n") or ""
        value2 = currIntf:match("[^#]DNS=%('(.-)'%)\n") or ""
        if value1 == "" and value2 == "" then
         currIntf = currIntf.."#DNS=\n"
        end
        currIntf = currIntf:gsub("#DNS", "DNS")
        if newNameServers ~= "" then
          currIntf = currIntf:gsub("DNS=.-\n", "DNS=( "..newNameServers..")\n")
        else
          currIntf = currIntf:gsub("DNS=.-\n", "")
        end
      end
      -- End add NameServers to file 
      
      if newSearch ~= interface.domain then
        if interface.domain == "" then
         currIntf = currIntf.."#Domain=\n"
        end
        currIntf = currIntf:gsub("#Domain", "Domain")
        if newSearch ~= "" then
          currIntf = currIntf:gsub("Domain=.-\n", "Domain=('"..newSearch.."')\n")
        else
          currIntf = currIntf:gsub("Domain=.-\n", "")
        end
      end
      
      
      if interface.type == "wwan" then
         newAPN = cgi.post.apn or ""
         newUser = cgi.post.username or ""
         newPasswd = cgi.post.password or ""
        if newAPN ~= "" then
           currIntf = currIntf:gsub("#AccessPointName","AccessPointName")
           currIntf = currIntf:gsub("AccessPointName=.-\n","AccessPointName="..newAPN.."\n")
        else
           currIntf = currIntf:gsub("[^#]AccessPointName","\n#AccessPointName")
        end
        if newUser ~= "" then
           currIntf = currIntf:gsub("#User","User")
           currIntf = currIntf:gsub("User=.-\n","User='"..newUser.."'\n")
        else
           currIntf = currIntf:gsub("[^#]User","\n#User")
        end
        if newPasswd ~= "" then
           currIntf = currIntf:gsub("#Password","Password")
           currIntf = currIntf:gsub("Password=.-\n","Password='"..newPasswd.."'\n")
        else
           currIntf = currIntf:gsub("[^#]Password","\n#Password")
        end
          
      end
      

     command.writefile(network_conf.netctl_profile_path.."/"..intfName, currIntf)

     if newEnabled ~= interface.enabled then
        if newEnabled == "enabled" then
           command.ex([[netctl enable ]]..intfName)
        else
           command.ex([[netctl disable ]]..intfName)
        end
     end

        interface.address = newAddress
        interface.netmask = newNetmask
        interface.gateway = newGateway
        interface.method = newMethod
        interface.dns = newNameServers
        
        nameservers = {}
        for i in interface.dns:gmatch("%S+") do
        server = i:gsub("%'", "") or nil
          if server ~= nil then
            table.insert(nameservers, server)
          end
        end
        
        interface.domain = newSearch
        interface.enabled = newEnabled
        
        
        if interface.type == "wwan" then
           interface.apn = newAPN
           interface.user = newUser
           interface.password = newPasswd
        end
        

        if interface.enabled == "enabled" then
           command.ex([[netctl restart ]]..intfName)
        else
           command.ex([[netctl stop ]]..intfName)
        end
        msg(currIntf)    
    end

    
    ifconfigResult = currIntf
    
    
else
    -- Bail on error here
    content = [[
                    <div id="info"><center><H1>Network - Manage Interface</H1></center></div>
                    <div id="info">
                        <center>
                            <h2><img src="images/warning.png"/> Cannot load interface details</h2>
                            An invalid interface was selected, or the interface has not been marked<br>
                            as being configurable in the interfaces file "]]..network_conf.interface_file..[["<br><br>
                            <a href="network_interfaces.lua">View network interfaces</a> | <a href="network_status.lua">View network status</a>
                        </center>
                    </div>
]]
    html = header..content..footer
    print(html)
    return        
end    

content = ""
content = content .. [[
                    <script language="Javascript" type="text/javascript">
                    
                        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 loop;
                            for (loop = 0; loop < all_inputs.length; loop++)
                            {
                                all_inputs[loop].name = field+(loop+1);
                            }
                        }
                        
                        //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("input"); //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 = "<input name=\""+(field+(count+1))+"\" style=\"width:300px;\"/><a style=\"cursor:pointer;color:blue;\" onclick=\"removeField(this, '"+field+"');\"> <img src=\"images/trash.png\" alt=\"Delete\" title=\"Delete\"/></a>";
                                    field_area.appendChild(li);
                            }
                            else
                            {       //Older Method
                            }
                        }
                        

                        function check(area)
                        {
                            var inputs = area.getElementsByTagName("input");
                            if (!inputs[0].checked || inputs[1].checked)
                            {
                                inputs[2].readOnly = true;
                                inputs[3].readOnly = true;
                                inputs[4].readOnly = true;
                            }
                            else
                            {
                                inputs[2].readOnly = false;
                                inputs[3].readOnly = false;
                                inputs[4].readOnly = false;
                            }
                        }
                        
                        function ValidateIPaddress(inputText)  
                        {  
                            var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
                            if (inputText.match(ipformat))
                            {  
                                return true;  
                            }  
                            else  
                            {  
                                return false;  
                            }  
                        }
                        
                        function ValidateNetmask(inputText)
                        {
                           var num = parseInt(inputText,10)
                           console.log("Check NM")
                           if (!isNaN(num) && num > 0 && num <= 32)
                           {
                              return true
                           }
                           else
                           {
                              return false
                           }
                        }
                        
                        function ValidateForm(form,is_wwan)
                        {
                            if (form.getAttribute('submitted')) return false;
                            var inputs = form.getElementsByTagName("input");
                            var loop;
                            var errors = 0;
                            for (loop = 2; loop < 5; loop++)
                            {
                                inputs[loop].removeAttribute("invalidIP");
                                var warn = document.getElementById("invalidIP_"+loop);
                                if (warn)
                                {
                                    warn.parentNode.removeChild(warn);
                                }

                                if(loop != 3)
                                {
                                   if ((inputs[loop].value != "") && (!ValidateIPaddress(inputs[loop].value)) && (!inputs[loop].readOnly))
                                   {
                                      //alert("Input " + loop + " has an invalid IP address! " + inputs[loop].value);
                                      inputs[loop].setAttribute("invalidIP","true");
                                      errors++;
                                   }
                                }
                                else if ((inputs[loop].value != "") && !(ValidateNetmask(inputs[loop].value) || ValidateIPaddress(inputs[loop].value)) && (!inputs[loop].readOnly))
                                {
                                      inputs[loop].setAttribute("invalidIP","true");
                                      errors++;
                                }
                                
                                if (inputs[loop].getAttribute("invalidIP") === "true")
                                {
                                    var warn = document.createElement("span");
                                    warn.id = "invalidIP_"+loop;
                                    warn.innerHTML = " <img src='images/warning.png' alt='Invalid IP' title='Invalid IP'/>";
                                    inputs[loop].parentNode.appendChild(warn);
                                }
                            }
                            if (errors)
                            {
                                alert("You have entered one or more invalid IP addresses.\nPlease fix the indicated addresses.");
                                return false;
                            }
                            else
                            {
                                form.setAttribute('submitted','true');
                                return true;
                            }
                        }

                    </script>
                    <div id="info">
                        <div style="background:url(images/network.png); background-size:32px; background-repeat:no-repeat; background-position: 20px center;">
                            <center><h1>Network - Interfaces</h1></center>
                        </div>
                    </div>
]]

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

if (interface ~= nil) then
    local wwan_type = "false"
    if interface.type == "wwan" then wwan_type = "true" end
    content = content .. [[
                    <h3>Managing Profile "]]..interface.name..[["</h3>
                    <div class="formLayoutfull">
                        <form action="network_manage.lua" method="post" onsubmit="return ValidateForm(this,]]..wwan_type..[[);">
                            
]]
    local dhcp_checked = ""
    local enable_checked = ""
    local read_only = inputControl
    if interface.method == "dhcp" then dhcp_checked = "checked" end
    if interface.enabled == "enabled" then enable_checked = "checked" end
    if interface.method == "dhcp" or interface.enabled ~= "enabled" then read_only="readonly" end
        content = content .. [[
                            <label for="enable">Enable this profile</label>
                            <input type="checkbox" value="enabled" name="profile" id="enable" ]]..enable_checked..[[ onchange="check(this.parentNode);"]]..buttonControl..[[/><br>
                            <label for="dhcp">Obtain automatically from DHCP</label>
                            <input type="checkbox" value="dhcp" name="method" id="dhcp" ]]..dhcp_checked..[[ onchange="check(this.parentNode);"]]..buttonControl..[[/><br>
                            <ul>
                                <li><label style="display: inline-block; width: 120px;">IP address:</label> <input type="text" name="address" value="]]..interface.address..[["]]..read_only..[[/></li>
                                <li><label style="display: inline-block; width: 120px;">Netmask:</label> <input type="text" name="netmask" value="]]..interface.netmask..[["]]..read_only..[[/></li>
                                <li><label style="display: inline-block; width: 120px;">Gateway:</label> <input type="text" name="gateway" value="]]..interface.gateway..[["]]..read_only..[[/></li>
                            </ul>
]]
    if (interface.type == "wwan") then
        content = content .. [[
        <hr>
        <h3>Modem settings: </h3>
        <ul>
           <li>
              <label style="display: inline-block; width: 120px;">APN: </label>
              <input type="text" name="apn" id="apn" value="]]..interface.apn..[["]]..inputControl..[[/>
           </li>
           <li>
               <label style="display: inline-block; width: 120px;">Username: </label>
               <input type="text" name="username" id="username" value="]]..interface.user..[["]]..inputControl..[[/>
           </li>
           <li>
               <label style="display: inline-block; width: 120px;">Password: </label>
               <input type="text" name="password" id="password" value="]]..interface.password..[["]]..inputControl..[[/>
           </li>
        </ul>
]]
    end
    
    content = content .. [[
                            <input type="hidden" name="interface" value="]]..interface.name..[["/>
                            <hr>
]]                            
    --if (saved == 1) then
    --    content = content .. [[
    --                        <br><b><img src="images/ok.png"/> Changes saved, but may take a few seconds to take effect.</b><br><br>
--]]
    --end
    --content = content .. [[
    --                        <input type="button" name="backButton" value="Back to Interfaces" onclick="window.location.assign('network_interfaces.lua');"/>
    --                        <input type="Submit" name="submitButton" value="Save and Apply"]]..buttonControl..[[/>
    --                    </form>
    --                </div> 
                    
    --                ]]
    -- Newly added DNS settings inside interface
    content = content .. [[
                        <div style="padding: 20px; border: solid 1px #aaaaaa;">
                          <h3>DNS Settings</h3>
                          <hr>
                          <br>
                          <label>List of domain name servers</label>
                          <ol id="server_list">
                        
  ]]
    if (#(nameservers) > 0) then
      for i = 1, #(nameservers) do
        content = content .. [[
                                <li><input type="text" name="server]]..i..[[" value="]]..nameservers[i]..[[" style="width:300px;"]]..inputControl..[[/>
                                <a style="cursor:pointer; color:blue;" onclick="]]..scriptControl..[[removeField(this, 'server');">
                                <img src="images/trash.png" alt="Delete" title="Delete"/></a></li>
  ]]
      end
    end
    
    content = content .. [[
                          </ol>
                          
                          <input type="button" value="Add Nameserver" onclick="addField('server', 10);"]]..buttonControl..[[ />
                          <br/>
                          <br/>
                          <hr/>
                          <br/>
                          <label>Search domain</label><input type="text" name="search" value="]]..interface.domain..[[" style="width: 300px;"]]..inputControl..[[ />
                          <br/>
                          <br/>
                        </div>
                        <br>
                        <hr/>
                        <br/>
    ]]
    if (saved == 1) then
        content = content .. [[
                            <br><b><img src="images/ok.png"/> Changes saved, but may take a few seconds to take effect.</b><br><br>
]]
    end
    content = content .. [[
                            <input type="button" name="backButton" value="Back to Interfaces" onclick="window.location.assign('network_interfaces.lua');"/>
                            <input type="Submit" name="submitButton" value="Save and Apply"]]..buttonControl..[[/>
                        </form>
                    </div> 
                   
                    ]]
                    --End of newly added DNS Settings
    content = content ..[[
                    <h3>Interface configuration</h3>
                    <pre class="formLayoutfull">
                    <!-- ifconfig start -->
]] 
.. ifconfigResult .. 
[[                  
                    <!-- ifconfig end -->
                    </pre>
]]
else
    content = content .. [[
                    <div id="info">
                        <center>
                            <h2><img src="images/warning.png"> No interfaces found</h2>
                            Either the interfaces file "]]..network_conf.interface_file..[[" is missing or unreadable,<br>
                            or none of the interfaces have been marked as being configurable.<br><br>
                            <a href="network_status.lua">View network status</a> for more information.
                        </center>
                    </div>]]
end

print(header..content..footer)
