#!/bin/env lua

require "jester.conf"
require "jester.core"
require "jester.debug"
require "jester.help"

jester.help.init_module_help()

--[[
  Grab a comma separated list of all available actions.
]]
function actions_list()
  local actions = jester.help.get_actions()
  local ordered_actions = table.orderkeys(actions)
  return table.concat(ordered_actions, ", ")
end

--[[
  Output for keys-type parameters.
]]
function keys_table()
  return [[{
      ["1"] = "",
      ["2"] = "",
      ["3"] = "",
      ["4"] = "",
      ["5"] = "",
      ["6"] = "",
      ["7"] = "",
      ["8"] = "",
      ["9"] = "",
      ["0"] = "",
      ["*"] = "",
      ["#"] = "",
    }]]
end

function get_user_input()
  local actions_help = string.format([[Enter a space separated list of actions for the sequence, in the order they should be run.  Possible actions include:

%s

Actions: ]], actions_list())
  io.write(actions_help)
  local actions = io.read("*line")

  local variables_help = string.format([[Enter a space separated list of variable names that you will use to store channel variables.

Variable names (channel): ]], actions_list())
  io.write(variables_help)
  local variables = io.read("*line")

  local storage_help = string.format([[Enter a space separated list of variable names that you will use to store data pulled from Jester storage areas.

Variable names (storage): ]], actions_list())
  io.write(storage_help)
  local storage = io.read("*line")
  return actions, variables, storage
end

-- Channel variables templates.
function build_variables_output(variables)
  local output = ""
  variables = string.trim(variables)
  if variables ~= "" then
    variables = string.split(variables, " ")
    for _, v in ipairs(variables) do
      output = output .. v .. [[ = variable("")]] .. "\n"
    end
  end
  return output
end

-- Storage variables templates.
function build_storage_output(storage)
  local output = ""
  storage = string.trim(storage)
  if storage ~= "" then
    storage = string.split(storage, " ")
    for _, v in ipairs(storage) do
      output = output .. v .. [[ = storage("", "")]] .. "\n"
    end
  end
  return output
end

-- Actions templates.
function build_actions_output(actions)
  local output = ""
  local output_table = {}
  local skipped_actions = {}
  local params, params_table, param_value
  local all_actions = jester.help.get_actions()
  -- Loop through all provided actions.
  for _, v in ipairs(actions) do
    -- Make sure the action is a valid one.
    if all_actions[v] then
      params_table = {}
      -- Add the action parameter first.
      table.insert(params_table, [[    action = "]] .. v .. [[",]])
      -- Check for action parameters.
      if all_actions[v].params then
        params = table.orderkeys(all_actions[v].params) 
        for _, param in ipairs(params) do
          -- These parameters get special output.
          if param == "keys" or param == "key_announcements" then
            param_value = keys_table()
          else
            param_value = ""
          end
          -- Add the parameter to the list.
          table.insert(params_table, [[    ]] .. param .. [[ = ]] .. param_value .. [[,]])
        end
      end
      -- Build the entire action as a string.
      output = "  {\n"
      output = output .. table.concat(params_table, "\n") 
      output = output .. "\n  },"
      table.insert(output_table, output)
    else
      table.insert(skipped_actions, "  " .. v)
    end
  end
  return table.concat(output_table, "\n"), skipped_actions
end

function build_full_sequence()
  local output = ""
  local skipped_actions = {}
  local action_output
  -- Get user input for what to build.
  local actions, variables, storage = get_user_input()
  output = output .. build_variables_output(variables)
  output = output .. build_storage_output(storage)
  actions = string.trim(actions)
  -- Build actions if present.
  if actions ~= "" then
    output = output .. "\nreturn\n{\n"
    actions = string.split(actions, " ")
    action_output, skipped_actions = build_actions_output(actions)
    output = output .. action_output
    output = output .. "\n}\n"
  end
  return output, skipped_actions
end

arguments = {...}

local output, preview
local skipped_actions = {}

-- Arguments were passed, use them to build actions instead of full output.
if #arguments > 0 then
  if arguments[1] == "keys" then
    preview = "    keys = " .. keys_table() .. ",\n"
  else
    output, skipped_actions = build_actions_output(arguments)
    preview = output .. "\n"
  end
-- Build a full sequence.
else
  output, skipped_actions = build_full_sequence()
  preview = string.format([[

Generated sequence:

%s
Above is the sequence template generated by jsequence.  To write this sequence to a file in the current directory, enter the sequence name below, or press enter to exit jsequence.

Write sequence (enter to skip): ]], output)
end

-- Catch any bad actions and warn the user.
if #skipped_actions > 0 then
  local warning = string.format([[

WARNING: the following actions are invalid, and were not included:
%s
]], table.concat(skipped_actions, "\n"))
  preview = warning .. preview
end

-- Display a preview to the user.
io.write(preview)

-- Optionally write to file if a full sequence was built.
if #arguments == 0 then
  local filename = io.read("*line")
  if filename and filename ~= "" then
    -- Add a .lua extension, aids in IDE/syntax coloring.
    filename = filename .. ".lua"
    local file, error_message = io.open(filename, "w")
    local message
    if file then
      file:write(output)
      message = string.format([[Sequence written successfully to '%s']], filename)
    else
      message = string.format([[Error writing file: %s"]], error_message)
    end
    io.write(message .. "\n")
  end
end

