#!/usr/bin/env ruby
require 'date'
# TODO: this.
# Take a file as first argument, which is to be the file biblio.csv, containing
# all books read. Then formats this as a table. It sorts the books in
# the order [Ongoing, Completed, Yet to Read], and replaces several values with
# ones more appropriate for viewing pleasure.
# For the final column (index: 11, zero-indexed) we replace the contents with a
# link. So rd/the-progress-of-a-crime becomes
# For column 3 (Part), this is rounded as special logic.
# \n"
  exit
end
# def do_header(h: str): str
# Returns the rows of the table corresponding to the header.
def do_header(h)
  s = "\t\n"
  return s
end
# Make the string look sexy, ooh la la.
def sexify(val)
  # Round integers if they end .00.
  if val.end_with? ".00" then 
    integral = val.to_i
    unless integral == 0
      return integral.to_s
    end
  end
  # Transform strings.
  if $status_transform.has_key? (val)
    return $status_transform[val]
  end
  if $form_transform.has_key? (val)
    return $form_transform[val]
  end
  if $ownership_transform.has_key? (val)
    return $ownership_transform[val]
  end
  if $general_transform.has_key? (val)
    return $general_transform[val]
  end
  return val
end
ret=""
header=""
# Contains the buckets into which to put the entries.
unknown = [] # typeof(unknown) == array[str]
known   = {} # typeof(known)   == Hash[str => array[str]]
def written_month_of(ym)
  # Takes, e.g. "2023-09" and returns "September 2023". Invariant: entry must 
  # be of form "YYYY-MM".
  month = ym[-2..-1]
  ret = ""
  month_name = Date::MONTHNAMES[month.to_i]
  ret << month_name << " " << ym[0..3]
  return ret
end
def wrap_entries_in_table(entries, header)
  # Call after string made of all entries. This fn wraps them into the table.
  ret = ""
  ret << "
\n" \
      << header \
      << entries \
      << "
\n"
  return ret
end
def make_html_entry(entry) 
  # Makes a singular entry.
  ret = ""
  ret << "\t\n"
  entry.split($delim).each_with_index do |e, i|
    next if i == 0 or i == 6 or i == 7 or i == 8 or i == 9
    e = e.delete "\n"
    if i == 11 and e != "N/A" then 
      ret << "\t\t| Link\n"
    else
      ret << "\t\t | " \
          << sexify(e) \
          << "\n"
    end
  end
  
  ret << "\t | 
\n"
  return ret
end
File.foreach(ARGV[0]).with_index do |line, line_num|
  # 0. If entry not completed, skip, otherwise ...; [done]
  # 1. Figure out what month the line corresponds to;
  # 2. Chuck line into a bucket corresponding to entries in that month;
  # 3. Sorting that bucket into the right month, and make the table out of the
  #    entries.
  if line_num == 0 then # Must go first, otherwise skipped by checks below.
    header << do_header(line)
  end
  next if line == "\n" or line == "\t" or line == "" or line == " " or line == $delim
  next if not line.include? "completed;"
  finished_date = line.split($delim)[5]
  if finished_date == "" or finished_date == "\t" or finished_date == "N/A" then 
    unknown = unknown.append line
  else
    # Invariant: everything completed is either unknown date, or has at least
    # a year and a month (but not necessarily a day). We use this, e.g. 
    # "2023-01", as the index for the month.
    index = finished_date[0..6]
    # It is possible for the index not to be added here, so if this is the case
    # just add the index as [] and then we directly append to what we've just 
    # added.
    if not known.has_key? (index) 
      known[index] = []
    end
    # And now we can append.
    known[index] = (known[index] << line)
  end
end
# Sort hash, so we can simply iterate over it.
known = known.sort.reverse.to_h
# Make HTML for "Unknown"s
unknown = unknown.map! { |entry| make_html_entry(entry) }.join ("\n")
unknown_table = wrap_entries_in_table(unknown, header) # typeof == str
unkn_ret = ""
unkn_ret << "Unknown
\n" \
         << unknown_table
kn_rets = []
# Make HTML for each month.
known.each do |key, values|
  # Here, values is an array of all entries. We want to merge then together,
  # and thereby get the table.
  values = values.map! { |value| make_html_entry(value) }.join ("\n")
  known_table = wrap_entries_in_table(values, header) # typeof == str
  kn_ret = ""
  kn_ret << "" \
         << written_month_of(key) \
         << "
\n" \
         << known_table
  kn_rets = kn_rets.append(kn_ret)
end
# File.foreach(ARGV[0]).with_index do |line, line_num| 
#   next if line == "\n" or line == "\t" or line == "" or line == " " or line == $delim
# 
#   # Handle the first line - the header.
#   if line_num == 0 then 
#     header << do_header(line)
#   else
#     # We need to figure out whether it is ongoing, completed, or yet to read.
#     # To do this, we will check if the corresponding string is in the line.
#     if line.include? "completed;" then 
#       target = table_cmp 
#     elsif line.include? "ongoing;" then 
#       target = table_ongoing
#     elsif line.include? "dropped;" then 
#       target = table_drp
#     else
#       target = table_rest
#     end
# 
#   end
# end
# Echo the file. 
puts kn_rets
puts unkn_ret