#!/usr/bin/lua

require 'posix'
List = require 'pl.List'
stringx = require 'pl.stringx'
file = require 'pl.file'

-- seed random number generator
seed = posix.unistd.getpid() * os.time()
seed = seed % (2^31)
math.randomseed(seed)

-- return a random integer in the range 1..value
function randomval (value)
  return (math.ceil(math.random() * value))
end

-- split a string on a delimiter (stripping whitespice around delimiters)
function split(str, delim)
  delim = delim and ('%s*'..delim..'%s*') or '%s+'
  local t = List.new()
  local fpat = '(.-)'..delim
  local last_end = 1
  local s, e, cap = str:find(fpat, 1)
  while s do
    if s ~= 1 or cap ~= "" then
      t:append(cap)
    end
    last_end = e + 1
    s, e, cap = str:find(fpat, last_end)
  end
  if last_end <= #str then
    cap = str:sub(last_end)
    t:append(cap)
  end
  return t 
end

-- select a random member of a List
function pickone (choices)
  return (split(choices[randomval(#choices)]))
end

-- return the index of the first word in wordlist that is a key in dict
function find_key (dict, wordlist)
  for i = 1, #wordlist do
    if (dict[wordlist[i]]) then
      return i
    end
  end
  return nil
end

-- Recursively process a list of words, expanding the dictionary keys into
-- randomly-selected replacement phrases"
function generate_phrase (words)
  if #words == 0 then
    return List.new()
  end

  local left, choices, right
  local divvy = function(i)
    left = words:slice(1, i-1)
    choices = repl[words[i]]
    right = words:slice(i+1, -1)
  end

  local i = find_key(repl, words)
  if i and pcall(divvy, i) then
    return (left .. generate_phrase(pickone(choices)..right))
  else
    return (words)
  end
end

-- load the data file
function load_data (filename)
  filename = filename or "/ext/www/foods.txt"

  local content = file.read(filename)
  local data = stringx.splitlines(content)
  sentence = data:pop(1)
  repl = List.new()

  for i,line in pairs(data) do
    line = split(line, ':')
    repl[line:pop(1)] = line       -- store replacement phrases in dictionary
  end
end

-- capitalize the first letter of a string
function capitalize (str)
  return (str:sub(1,1):upper()..str:sub(2))
end

--
-- main
--
load_data()

n = arg[1] or 1

-- generate a random sentence
for i = 1, n do
  food = generate_phrase(split(sentence)):join(' ')
  print (capitalize(food))
end
