# csv2gph.awk version 4 by Ben Collver
# Convert CSV file to gopher map, emitting items for links found.

# Assumes first line of CSV is a header with field names.

# print_wrap() will break long lines into line continuations

function print_wrap(str, len) {
   line = 1
   buf = str
   while (length(buf) > len) {
       chunk = substr(buf, 1, len)
       if (match(chunk, / [^ ]*$/)) {
           before = substr(buf, 1, RSTART-1)
           after = substr(buf, RSTART+1)
           print "  " before
           buf = after
       } else if (match(chunk, /-[^-]*$/)) {
           before = substr(buf, 1, RSTART)
           after = substr(buf, RSTART+1)
           print "  " before
           buf = after
       } else {
           break
       }
       line++
   }
   print "  " buf
}

function uri_encode(value,    retval) {
    retval = value
    # do not double-encode value
    if (retval !~ /%/) {
        # URI encode a few choice characters
        gsub(/ /, "%20", retval)
        gsub(/&/, "%26", retval)
        gsub(/=/, "%3D", retval)
        gsub(/?/, "%3F", retval)
    }
    return retval
}

BEGIN {
    path = SRC
    gsub(/^.*public_gopher/, "/~bencollver", path)
    printf "[0|View source (CSV)|%s|server|port]\n\n", path
    gsub(/^.*\//, "", path)
    printf "# %s\n\n", path
}

NR == 1 {
   for (i = 1; i <= NF; i++) {
       header[i] = $i
       if (length($i) > maxlen) {
           maxlen = length($i)
       }
   }
   maxlen++
}

NR > 1 {
   for (i = 1; i <= NF; i++) {
       # When a value contains URL(s), handle pipe separated sub-values
       if ($i ~ /:\/\//) {
           count = split($i, val, /\|/)
       } else {
           count = 1
           val[1] = $i
       }

       for (j = 1; j <= count; j++) {
           if (j > 1) {
               head = header[i] " " j ":"
           } else {
               head = header[i] ":"
           }
           value = val[j]
           label = value
           len = maxlen + 2 + length(label)
           if (len > 68) {
               label = "..." substr(label, 3 + (len - 68))
           }
           if (match(value, /^gopher:\/\//)) {
               str = substr(value, RLENGTH + 1)
               if (match(str, /^[^\/:]*/)) {
                   host = substr(str, 1, RLENGTH)
                   str = substr(str, RLENGTH + 1)
               } else {
                   host = "server"
               }
               if (match(str, /^:[0-9][0-9]*/)) {
                   port = substr(str, 2, RLENGTH - 1)
                   str = substr(str, RLENGTH + 1)
               } else {
                   port = "70"
               }
               if (match(str, /^\/[0-9a-z]/)) {
                   type = substr(str, 2, 1)
                   str = substr(str, 3)
               } else {
                   print "Error: Count not determine gopher type for URL " \
                       value
                   exit 1
               }
               path = str
               printf "[%s|%-" maxlen "s %s|%s|%s|%s]\n",
                   type, head, label, path, host, port
           } else if (value ~ /^(ftp|https?):/) {
               value_code = uri_encode(value)
               if (value_code ~ /%/) {
                   # work around geomyidae bug on tilde.pink
                   host = "tilde.club"
                   port = "70"
               } else {
                   host = "server"
                   port = "port"
               }
               printf "[h|%-" maxlen "s %s|URL:%s|%s|%s]\n",
                   head, label, value, host, port
           } else {
               if (len > 70) {
                   printf "%-" maxlen "s\n", head
                   print_wrap(value, 70)
               } else {
                   printf "%-" maxlen "s %s\n", head, value
               }
           }
       }
   }
   printf "\n"
}