# shellcheck.awk version 1
# lint a shell script using shellcheck.net
# depends on curl and json2tsv being in your path

function gettemp(     result, retval) {
   while ((cmd_mktemp | getline) > 0) {
       retval = $0
   }
   result = close(cmd_mktemp)
   if (result != 0) {
       print "Error: mktemp failed exit status: " result
       exit
   }
   if (length(retval) == 0) {
       print "Error: mktemp failed, no tmpfile"
       exit
   }
   return retval
}

function main(    cmd, code, col, col2, curlcfg, jsout, level,
   line, line2, message, script, scout)
{
   if (ARGC < 2) {
       print "Usage: shellcheck.awk [script.sh]"
       exit
   }
   curlcfg = gettemp()
   jsout = gettemp()
   scout = gettemp()
   script = ARGV[1]

   printf "--connect-timeout 10\n" > curlcfg
   printf "--max-redirs 0\n" >> curlcfg
   printf "--proto =https\n" >> curlcfg
   printf "--show-error\n" >> curlcfg
   printf "--silent\n" >> curlcfg
   printf "--url %s\n", api_url >>curlcfg
   printf "--form script=<\"%s\"\n", script >>curlcfg
   printf "--output %s\n", jsout >>curlcfg
   close(curlcfg)

   cmd = sprintf("%s -K %s 2>&1", cmd_curl, curlcfg)
   system(cmd)
   cmd = sprintf("%s <%s >%s 2>&1", cmd_json2tsv, jsout, scout)
   system(cmd)

   FS = "\t"
   while ((getline <scout) > 0) {
       if ($1 == "[]" && $2 == "o" && code > 0) {
           printMsg(script, code, col, col2, line, line2, level, message)
           code = 0
           col = 0
           col2 = 0
           level = ""
           line = 0
           line2 = 0
           message = ""
       } else if ($1 == "[].code" && $2 == "n") {
           code = $3
       } else if ($1 == "[].column" && $2 == "n") {
           col = $3
       } else if ($1 == "[].endColumn" && $2 == "n") {
           col2 = $3
       } else if ($1 == "[].level" && $2 == "s") {
           level = $3
       } else if ($1 == "[].line" && $2 == "n") {
           line = $3
       } else if ($1 == "[].endLine" && $2 == "n") {
           line2 = $3
       } else if ($1 == "[].message" && $2 == "s") {
           message = $3
       }
   }
   close(scout)
   if (code > 0) {
       printMsg(script, code, col, col2, line, line2, level, message)
   }

   unlink(curlcfg)
   unlink(jsout)
   unlink(scout)
   return
}

function printMsg(script, code, col, col2, line, line2, level,
   message)
{
   if (line == line2) {
       printf "Line %d:\n", line
   } else {
       printf "Lines %d-%d:\n", line, line2
   }

   NR = 0
   while ((getline <script) > 0) {
       NR++
       if (NR >= line && NR <= line2) {
           print
       }
   }
   close(script)

   printf "%s^-- (%s): %s\n", repeat(" ", col - 1), level, message
   printf "https://www.shellcheck.net/wiki/SC%d\n\n", code
   return
}

function repeat(str, count,     retval) {
   if (count > 0) {
       retval = sprintf("%" count "s", " ")
       gsub(/ /, str, retval)
   }
   return retval
}

function unlink(name) {
   system(cmd_rm " " name)
   return
}

BEGIN {
   api_url = "https://www.shellcheck.net/shellcheck.php"
   cmd_curl = "/usr/bin/curl"
   cmd_json2tsv = "json2tsv"
   cmd_mktemp = "/bin/mktemp"
   cmd_rm = "rm"
   main()
}