# TOML Implementation in mq
# Based on TOML v1.0.0 specification

def _escape_string(str):
  replace(str, "\\", "\\\\") | replace("\"", "\\\"") | replace("\n", "\\n") | replace("\t", "\\t")
end

def _add_toml_lines(lines, key, value):
  if (is_dict(value)):
    do
      let body_lines = map(keys(value), fn(k): k + " = " + _toml_stringify_value(value[k]);)
      | let last_line = last(body_lines)
      | let last_line = if (last_line): last_line + "\n" else: None
      | lines + ["[" + key + "]"] + body_lines[0:len(body_lines) - 1] + last_line
    end
  elif (is_array(value)):
    lines + ["[[" + key + "]]"] + if (len(value) == 0): _toml_stringify_value(first(value)) else: map(value, fn(v): _toml_stringify_value(v) + ", ";)
  else: lines + [key + " = " + _toml_stringify_value(value)]
end

def _toml_stringify_value(value):
  if (is_string(value)):
    "\"" + _escape_string(value) + "\""
  elif (is_number(value)):
    to_string(value)
  elif (is_bool(value)):
    if (value): "true" else: "false"
  elif (is_array(value)):
    "[" + join(map(value, _toml_stringify_value), ", ") + "]"
  elif (is_dict(value)):
    "{" + join(map(keys(value), fn(k): k + " = " + _toml_stringify_value(value[k]);), ", ") + "}"
  elif (is_none(value)):
    ""
  else:
    to_string(value)
end

# Parses a TOML string and returns the parsed data structure.
def toml_parse(input):
  _toml_parse(to_string(input))
end

# Converts a data structure to a TOML string representation.
def toml_stringify(data):
  let lines = []
  | let result = keys(data)
  | var i = 0
  | let final_lines = while (i < len(result)):
      let key = result[i]
      | let value = data[key]
      | let lines = _add_toml_lines(lines, key, value)
      | i += 1
      | lines
    end
  | join(final_lines, "\n")
end

# Converts a data structure to a JSON string representation.
def toml_to_json(data):
  if (is_dict(data)):
    "{" + join(map(keys(data), fn(k): "\"" + k + "\":" + toml_to_json(data[k]);), ",") + "}"
  elif (is_array(data)):
    "[" + join(map(data, toml_to_json), ",") + "]"
  elif (is_string(data)):
    "\"" + _escape_string(data) + "\""
  elif (is_number(data)):
    to_string(data)
  elif (is_bool(data)):
    if (data): "true" else: "false"
  elif (is_none(data)):
    "null"
  else:
    "\"" + to_string(data) + "\""
end

def _create_array_markdown_table(data):
  let headers = keys(first(data))
  | let header_row = "| " + join(headers, " | ") + " |"
  | let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
  | let data_rows = map(data, fn(row):
      "| " + join(map(headers, fn(header): if (is_none(row[header])): "" else: replace(to_string(row[header]), "\n", "\\n");), " | ") + " |"
    end)
  | [header_row, separator_row] + data_rows
  | join("\n")
end

def _create_dict_markdown_table(data):
  let headers = ["Key", "Value"]
  | let header_row = "| " + join(headers, " | ") + " |"
  | let separator_row = "| " + join(map(headers, fn(_): "---";), " | ") + " |"
  | let data_rows = map(keys(data), fn(key):
      "| " + key + " | " + (if (is_none(data[key])): "" else: replace(to_string(data[key]), "\n", "\\n")) + " |"
    end)
  | [header_row, separator_row] + data_rows
  | join("\n")
end

def _create_simple_markdown_table(data):
  "| Value |\n| --- |\n| " + to_string(data) + " |"
end

# Converts a TOML data structure to a Markdown table.
def toml_to_markdown_table(data):
  if (is_array(data)):
    _create_array_markdown_table(data)
  elif (is_dict(data)):
    _create_dict_markdown_table(data)
  else:
    _create_simple_markdown_table(data)
end
