# Based on YAML 1.2 specification

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

def _yaml_stringify_value(value, indent_level):
  let indent = repeat(" ", indent_level * 2)
  | if (is_string(value)):
      if (contains(value, "\n") || contains(value, "\"") || contains(value, "'")):
        "\"" + _escape_string(value) + "\""
      else:
        value
    elif (is_number(value)):
      to_string(value)
    elif (is_bool(value)):
      if (value): "true" else: "false"
    elif (is_none(value)):
      "null"
    elif (is_array(value)):
      if (is_empty(value)):
        "[]"
      else:
        join(map(value, fn(item): "\n" + indent + "- " + _yaml_stringify_value(item, indent_level + 1);), "")
    elif (is_dict(value)):
      if (is_empty(keys(value))):
        "{}"
      else:
        join(map(keys(value), fn(k): "\n" + indent + k + ": " + _yaml_stringify_value(value[k], indent_level + 1);), "")
    else:
      to_string(value)
end

# Parses a YAML string and returns the parsed data structure.
def yaml_parse(input):
  _yaml_parse(to_string(input))
end

# Converts a data structure to a YAML string representation.
def yaml_stringify(data):
  if (is_array(data)):
    if (is_empty(data)):
      "[]"
    else:
      join(map(data, fn(item): "- " + _yaml_stringify_value(item, 1);), "\n")
  elif (is_dict(data)):
    if (is_empty(keys(data))):
      "{}"
    else:
      join(map(keys(data), fn(k): k + ": " + _yaml_stringify_value(data[k], 1);), "\n")
  else:
    _yaml_stringify_value(data, 0)
end

# Converts a YAML data structure to a Markdown table.
def yaml_to_markdown_table(data):
  if (is_array(data)):
    do
      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
  elif (is_dict(data)):
    do
      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
  else:
    "| Value |\n| --- |\n| " + to_string(data) + " |"
end

# Converts a data structure to a JSON string representation.
def yaml_to_json(data):
  if (is_dict(data)):
    "{" + join(map(keys(data), fn(k): "\"" + k + "\": " + yaml_to_json(data[k]);), ", ") + "}"
  elif (is_array(data)):
    "[" + join(map(data, yaml_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

# Converts a data structure to a YAML front matter string.
def to_front_matter(data):
  "---\n" + yaml_stringify(data) + "\n---"
end

