function http(method, remote, callback, body) {
   var xmlhttp = new XMLHttpRequest();
   xmlhttp.onreadystatechange = function() {
      if (xmlhttp.readyState == XMLHttpRequest.DONE) {
         callback(xmlhttp.responseText, xmlhttp.status)
      }
   };
   xmlhttp.open(method, remote, true);
   if (typeof body == "undefined") {
      body = null
   }
   xmlhttp.send(body);
}

function upsert() {
   function cb(body, status) {
      if (status == 200) {
         init()
      } else {
         console.log("error upserting:", status, body)
      }
   }
   console.log("to upsert", jsonifyForm("upsert"))
   http("POST", "/api/job/upsert", cb, jsonifyForm("upsert"))
}

function jsonifyForm(id) {
   var form = document.getElementById(id)
   var entries = new FormData(form).entries();
   var json = Object.assign(...Array.from(entries, ([x,y]) => ({[x]:y})));
   json.disabled = json.disabled == "false"
   var s = JSON.stringify(json)
   return s
}

function init() {
   var table = document.getElementById("jobs").getElementsByTagName("tbody")[0]
   function cb(body, status) {
      var jobs = JSON.parse(body)
      getJobsTable().innerHTML = ""
      jobs.forEach(function(job) {
         var s = format(job)
         inject(s)
      })
   }
   http("GET", "/api/job/list", cb, null)
}

function format(job) {
   var pause = "&#9208"
   var passing = "9711"
   if (job.last.status != 0) {
      passing = "129314"
      passing = "129324"
   }
   passing = `&#${passing};`
   var buttons = ""
   var btns = [
      {"name":"refresh", "icon":"8635"},
      {"name":"run", "icon":"9654"}, 
      {"name":"modify", "icon":"9999"}, 
      {"name":"delete", "icon":"10006"}
   ]
   btns.forEach(function(e) {
      buttons += `
         <span>
            <input type="button" onclick="job${e.name}(this);" value="&#${e.icon};" alt="${e.name}" title="${e.name}" job="${btoa(JSON.stringify(job))}"/>
         </span>
      `
   })
   var strikethrough = "initial"
   if (job.disabled) 
      strikethrough = "line-through"
   strikethrough = "text-decoration: "+strikethrough
   return `<tr><td><details>
      <summary name="${job.id}">
         <span style="${strikethrough}">${job.title}</span>
         <span>${passing}</span>
         ${buttons}
      </summary>
      <table>
         <tr><td>
            <code style="${strikethrough}">${job.cron}</code>
            <code>${job.language}</code>
         </td></tr>
         <tr><td>
            <code>${job.last.run}</code>
            <code>${job.last.runtime}</code>
         </td></tr>
         <tr><td>
            <code>${job.script}</code>
         </td></tr>
         <tr><td>
            <code>${job.last.output}</code>
         </td></tr>
      </table>
   </details></td></tr>`
}

function inject(s) {
   getJobsTable().innerHTML += s
}

function getJobsTable() {
   return document.getElementById("jobs").getElementsByTagName("tbody")[0]
}

init()

function jobdisable(input) {
   jobmodify(input)
   getField("disabled").checked = true
}

function jobenable(input) {
   jobmodify(input)
   getField("disabled").checked = false
}

function jobrun(input) {
   var job = jobFromInput(input)
   function cb(body, status) {
      if (status != 200) {
         console.log("failed to run job: ", status, body)
      }
   }
   http("GET", "/api/job/run/"+job.id, cb, null)
}

function jobmodify(input) {
   var form = getForm()
   var job = jobFromInput(input)
   var fields = ["id", "language", "cron", "script", "disabled", "title"]
   fields.forEach(function(field) {
      var e = getField(field)
      e.checked = job[field]
      e.value = job[field]
   })
   var details = form.parentElement
   details.setAttribute("open", "")
}

function jobdelete(input) {
   var job = jobFromInput(input)
   if (!confirm(`Delete the job "${job.title}"?`))
      return
   function cb(body, status) {
      var tr = getJobElement(job.id)
      tr.parentNode.removeChild(tr)
   }
   http("DELETE", "/api/job/delete/"+job.id, cb, null)
}

function jobrefresh(input) {
   var job = jobFromInput(input)
   function cb(body, status) {
      var table = getJobsTable()
      var summaries = Array.from(table.getElementsByTagName("summary"))
      summaries.forEach(function(e) {
         if (e.getAttribute("name") == job.id) {
            e = e.parentElement
            var showing = false
            if (e.getAttribute("open") != null) {
               showing = true
            }
            e = e.parentElement.parentElement
            var table = document.createElement("table")
            table.innerHTML = format(JSON.parse(body))
            if (showing) {
               table.getElementsByTagName("details")[0].setAttribute("open", "")
            }
            e.innerHTML = table.innerHTML
         }
      })
   }
   http("GET", "/api/job/get/"+job.id, cb, null)
}

function getJobElement(id) {
   var table = getJobsTable()
   var summaries = Array.from(table.getElementsByTagName("summary"))
   var target = null
   summaries.forEach(function(e) {
      if (e.getAttribute("name") == id) {
         e = e.parentElement
         e = e.parentElement.parentElement
         target = e
      }
   })
   return target
}

function jobFromInput(input) {
   var b64 = input.getAttribute("job")
   var json = atob(b64)
   return JSON.parse(json)
}

function getForm() {
   return document.getElementById("upsert")
}

getForm().reset()

function getField(name) {
   var form = getForm()
   var matches = form.elements[name]
   return matches
}
