{#################################}
{### General json macros       ###}
{#################################}

{### Renders a key-value-pair ###}
{%  macro keyvalue(key, value) %}
{{ key }}:{{ value }}
{%  endmacro %}

{### Renders a sequence ###}
{%  macro sequence(key, data) %}
{{ key }}:
{%      for entry in data %}
  - {{ entry }}
{%      endfor %}
{%  endmacro %}

{### Renders a mapping ###}
{%  macro mapping(key, data, ignore_keys, render_key) %}
{%      set indent_width = 0 %}
{%      if render_key %}
{%          set indent_width = 1 %}
{{ key }}:
{%      endif %}
{%      for sub_key, sub_data in data %}
{%          if not sub_key in ignore_keys %}
{%              if sub_data is mapping %}
{{ mapping(sub_key, sub_data.items(), [], True) | indent(indent_width, True) -}}
{%              elif sub_data is string %}
{{ keyvalue(sub_key, sub_data) | indent(indent_width, True) -}}
{%              elif sub_data is sequence %}
{{ sequence(sub_key, sub_data) | indent(indent_width, True) -}}
{%              endif %}
{%          endif %}
{%      endfor %}
{%  endmacro %}

{#################################}
{### General RST macros        ###}
{#################################}

{### Make H1 headline ###}
{%  macro h1(title) %}
{%  set title_length = title|length %}
{{ '#' * title_length }}
{{ title }}
{{ '#' * title_length }}
{%  endmacro %}

{### Make H2 headline ###}
{%  macro h2(title) %}
{%  set title_length = title|length %}
{{ '*' * title_length }}
{{ title }}
{{ '*' * title_length }}
{%  endmacro %}

{### Make H3 headline ###}
{%  macro h3(title) %}
{%  set title_length = title|length %}
{{ title }}
{{ '=' * title_length }}
{%  endmacro %}

{### Make H4 headline ###}
{%  macro h4(title) %}
{%  set title_length = title|length %}
{{ title }}
{{ '-' * title_length }}
{%  endmacro %}

{### Make H5 headline ###}
{%  macro h5(title) %}
{%  set title_length = title|length %}
{{ title }}
{{ '^' * title_length }}
{%  endmacro %}

{### Make H6 headline ###}
{%  macro h6(title) %}
{%  set title_length = title|length %}
{{ title }}
{{ '"' * title_length }}
{%  endmacro %}

{### Make explicit target ###}
{%  macro explicit_target(target_name) %}

.. _{{ target_name | make_rst_ref() }}:

{%  endmacro %}

{### References an explicit target ###}
{%  macro ref(target_name, text) %}
:ref:`{{ text }} <{{ target_name | make_rst_ref() }}>`
{%-  endmacro %}

{#################################}
{### Interface.json macros     ###}
{#################################}

{### Renders a multiline documentation ###}
{%  macro documentation(lines) %}
{%      for line in lines %}
{{ line }}
{%      endfor %}
{%  endmacro %}

{### Renders a single var ###}
{% macro var(var_name, var_data, show_required=true, required=None) %}
{% if required == None %}
{%      set required = 'default' not in var_data %}
{% endif %}
{% set optional = '' %}
{% if show_required == true %}
{%      if required == true %}
{%          set optional = '<required>' %}
{%      elif required == false %}
{%          set optional = '<optional>' %}
{%      else %}
{%          include "required needs to be set" %}
{%      endif %}
{% endif %}
{% set var_type = var_data.type %}
{% if not var_data.type %}
{%      set var_type = "string/object" %}
{% endif %}
**{{ var_name }}**: *{{ var_type }}* {{ optional }}
{%-     if '$ref' in var_data %}{{ ' (' + ref(var_data['$ref'], var_data['$ref'] | make_rst_ref()) + ')' }}{% endif +%}
{# Add default value for config entries #}
{%      if 'default' in var_data %}
{%        if var_data.default is string %}
{%          set var_default = "\"" + var_data.default + "\"" %}
{%        else %}
{%          set var_default = var_data.default %}
{%        endif %}
*default: {{ var_default }}*
{%      endif %}
{%      if var_data.description %}
{%        for line in var_data.description.split('\n') %}
{%          if line != '' %}
 {{ line }}
{%          endif %}
{%        endfor %}
{%      endif %}
{%      if 'documentation' in var_data %}
{{ documentation(var_data['documentation']) | indent(1, True) -}}
{%      endif %}
{%      set ignore_keys = ['default', 'description', 'type', 'properties', 'documentation', '$ref', 'required', 'items'] %}
{%      set mapping_result = mapping( var_name, var_data.items(), ignore_keys, False) %}
{%      if mapping_result != '' %}
{{ mapping_result | literal_rst | indent(1, True) -}}
{%      endif %}
{%      if var_data.type == 'object' and 'properties' in var_data %}
 properties:
{%          if not 'required' in var_data %}
{%              set all_required = True %}
{%              set required_array = [] %}
{%          else %}
{%              set all_required = False %}
{%              set required_array = var_data.required %}
{%          endif %}
{{ vars(var_data.properties.items(), True, required_array, all_required) | indent(2, True) -}}
{%      endif %}
{%      if var_data.type == 'array' and 'items' in var_data %}
{{          var('array_item', var_data['items'], False, True) | indent(1, True) -}}
{%      endif %}
{%  endmacro %}

{### Renders a list of vars ###}
{% macro vars(vars, show_required=true, required=[], all_required=False) %}
{%      for var_name, var_data in vars %}
{%          if show_required == true %}
{%              if all_required %}
{%                  set is_required = True %}
{%              else %}
{%                  set is_required = var_name in required %}
{%              endif %}
{%          else %}
{%              set is_required = None %}
{%          endif %}
{{          var(var_name, var_data, show_required, is_required) -}}
{%      endfor %}
{% endmacro %}


{### Renders cmd result ###}
{%  macro cmd_result(result_data) %}
{{ var('Result', result_data, False) -}}
{%  endmacro %}

{### Renders single cmd argument ###}
{%  macro cmd_argument(arg_name, arg_data) %}
{{ var(arg_name, arg_data, True) -}}
{%  endmacro %}

{### Renders cmd arguments ###}
{%  macro cmd_arguments(args) %}
{%      for arg_name, arg_data in args %}
{{ cmd_argument(arg_name, arg_data) -}}
{%      endfor %}
{%  endmacro %}

{### Renders a single cmd ###}
{%  macro cmd(cmd_name, cmd_data) %}
{%      if 'result' in cmd_data %}
{%          set type_string = cmd_data.result.type %}
{%      else %}
{%          set type_string = 'void' %}
{%      endif %}
**{{ cmd_name }}**: *{{ type_string }}*
 {{ cmd_data.description }}
{%      if 'arguments' in cmd_data %}
{{ cmd_arguments(cmd_data.arguments.items()) | indent(1, True) -}}
{%      endif %}
{%      if 'result' in cmd_data %}
{{ cmd_result(cmd_data['result']) | indent(1, True) -}}
{%      endif %}
{%      if 'documentation' in cmd_data %}
{{ documentation(cmd_data['documentation']) | indent(1, True) -}}
{%      endif %}
{%  endmacro %}

{### Renders a list of cmds ###}
{%  macro cmds(cmds) %}
{%      for cmd_name, cmd_data in cmds %}
{{ cmd(cmd_name, cmd_data) -}}
{%      endfor %}
{%  endmacro %}


{### Renders a list of errors ###}
{% macro errors(errs, definitions) %}
{%      for err in errs %}
**{{ err }}** : {{ definitions[err] }}
{%      endfor %}
{% endmacro %}

{### Renders a list of error_categories ###}
{% macro error_categories(categories, error_definitions) %}
{%      for cat in categories %}
**{{ cat }}** :
{{ errors(categories[cat], error_definitions[cat]) | indent(1, True) -}}
{%      endfor %}
{% endmacro %}

{#################################}
{### types.json macros         ###}
{#################################}

{### Renders a single type ###}
{%  macro type(type_name, type_data, file_name) %}
{%      set target_name = '/' + file_name + '#/' + type_name %}
{{ explicit_target(target_name) -}}
{{ var(type_name, type_data, False) | rst_indent() -}}
{%  endmacro %}

{### Renders a list of types ###}
{%  macro types(types, file_name) %}
{%      for type_name, type_data in types %}
{{ type(type_name, type_data, file_name) -}}
{%      endfor %}
{%  endmacro %}

{#################################}
{### manifest.json macros      ###}
{#################################}

{### Renders a single config entry ###}
{%  macro config_entry(name, data) %}
{{ var(name, data, True) -}}
{%  endmacro %}

{### Renders a list of config entries ###}
{%  macro config(config_data) %}
{%      for entry_name, entry_data in config_data %}
{{ config_entry(entry_name, entry_data) -}}
{%      endfor %}
{%  endmacro %}

{### Renders a single impl ###}
{%  macro impl(name, data) %}
{%      set interface_target = 'everest_interfaces_' + data.interface %}
**{{ name }}**: {{ ref(interface_target, data.interface) }}
 {{ data.description }}
{%      if 'documentation' in data %}
{{ documentation(data['documentation']) | indent(1, True) -}}
{%      endif %}
{%      set ignore_keys = ['description', 'interface', 'documentation', 'config'] %}
{%      set mapping_result = mapping( name, data.items(), ignore_keys, False) %}
{%      if mapping_result != '' %}
X
{{ mapping_result | indent(1, True) -}}
Y
{%      endif %}
{%      if 'config' in data %}
 **config:**
{{ config(data.config.items()) | indent(2, True) -}}
{%      endif %}
{%  endmacro %}

{### Renders a list of impls ###}
{%  macro impls(impls) %}
{%      for impl_name, impl_data in impls %}
{{ impl(impl_name, impl_data) -}}
{%      endfor %}
{%  endmacro %}

{### Renders a single requirement ###}
{%  macro req(name, data) %}
{%      if not 'min_connections' in data %}
{%          set min_conns = 1 %}
{%      else %}
{%          set min_conns = data.min_connections %}
{%      endif %}
{%      if not 'max_connections' in data %}
{%          set max_conns = 1 %}
{%      else %}
{%          set max_conns = data.max_connections %}
{%      endif %}
{%      set conns = min_conns|string + ".." + max_conns|string %}
{%      if min_conns == max_conns %}
{%          set conns = min_conns|string %}
{%      endif %}
{%      set interface_target = 'everest_interfaces_' + data.interface %}
**{{ name }}**: {{ ref(interface_target, data.interface) }} {{conns}}
{%      set ignore_keys = ['interface'] %}
{%      set mapping_result = mapping( name, data.items(), ignore_keys, False) %}
{%      if mapping_result != '' %}
{{ mapping_result | indent(1, True) -}}
{%      endif %}
{%  endmacro %}

{### Renders a list of requirements ###}
{%  macro reqs(reqs) %}
{%      for req_name, req_data in reqs %}
{{ req(req_name, req_data) -}}
{%      endfor %}
{%  endmacro %}

{### Renders metadata ###}
{%  macro metadata(data) %}
{{ h2('Metadata') -}}
{{ h3('Authors') -}}
{%      for author in data['authors'] %}
| {{ author }}
{%      endfor %}

{{ h3('License') -}}
| {{ data['license'] }}

{%      set ignore_keys = ['authors', 'license'] %}
{%      set mapping_result = mapping('metadata', data.items(), ignore_keys, False) %}
{%      if mapping_result != '' %}
{{ h3('Misc') -}}
{{ mapping_result | indent(1, True) | rst_indent() -}}

{%      endif %}
{%  endmacro %}
