{#
  Copyright DB InfraGO AG and contributors
  SPDX-License-Identifier: Apache-2.0
#}
{% from 'common_macros.html.j2' import show_other_attributes, description, typed_name, linked_name, linked_name_with_icon, display_traceability, render_requirements_table %}

{% macro insert_work_item(object) %}
  {{ linked_name_with_icon(object) | safe }}
{% endmacro %}

{% macro add_class_dependencies(cls, classes) %}
  {% if cls and cls.xtype == "org.polarsys.capella.core.data.information:Class" and not cls in classes %}
    {{ classes.append(cls) }}
    {% if cls.super %}
      {{ add_class_dependencies(cls.super, classes) }}
    {% endif %}
    {% for property in cls.properties %}
      {% set type = None %}
      {% if "type" in property.__dir__() %}
        {% set type = property.type %}
      {% elif "abstract_type" in property.__dir__() %}
        {% set type = property.abstract_type %}
      {% endif %}
      {{ add_class_dependencies(type, classes) }}
    {% endfor %}
  {% endif %}
{% endmacro %}
{% macro insert_or_link(object, inserted) %}
  {% if object not in inserted %}
    {{ insert_work_item(object) | safe }}
    {{ inserted.append(object) }}
  {% else %}
    <p>{{ linked_name_with_icon(object) }}</p>
  {% endif %}
{% endmacro %}

<h1>Functional Interface Specification {{ object.name }}</h1>
<h2>Introduction</h2>
<p>
  This Functional Interface Specification (FIS) document specifies functional
  communications between the sub-systems / components / system elements /
  actors of the System under Consideration.
</p>

<h2>Context Diagram</h2>
<p>The following shows {{ object.name }} in its system-level context:</p>
{{ render_diagram(object, "context_diagram") }}

<h2>Interface Partners</h2>
{% set partner_a = object.source.owner %}
{% set partner_b = object.target.owner %}
<p>
  This document specifies <i>{{ object.name }}</i>, an interface between
  {{ linked_name_with_icon(partner_a) | safe }} and
  {{ linked_name_with_icon(partner_b) | safe }}.
</p>
<h3>{{ linked_name(partner_a) }}</h3>
{{ description(partner_a) | safe }}
<h3>{{ linked_name(partner_b) }}</h3>
{{ description(partner_b) | safe }}
<h2>Interface Description</h2>
<p>The interface enables the following functional interactions:</p>
{# todo: handle mesed up model state where a functional exchange was allocated, but then function was re-allocated to another component #}
{% set partner_a_provides = object.allocated_functional_exchanges | selectattr('source.owner.owner.uuid', "equalto", partner_a.uuid) | list %}
{% set partner_a_source_uuids = partner_a_provides | map(attribute="source.owner.uuid") | unique | list %}
{% set partner_b_provides = object.allocated_functional_exchanges | selectattr('source.owner.owner.uuid', "equalto", partner_b.uuid) | list %}
{% set partner_b_source_uuids = partner_b_provides | map(attribute="source.owner.uuid") | unique | list %}

{% macro describe_provided_functional_exchanges(exchanges, source, target, sources) %}
  <p>
    {{ linked_name_with_icon(source) | safe }} may use the interface to
    interact with (provide exchange items to)
    {{ linked_name_with_icon(target) | safe }}:
  </p>
  <table>
    <thead>
      <tr>
        <th>Source function</th>
        <th>Interaction or Exchange Items</th>
        <th>Target function</th>
      </tr>
    </thead>
    <tbody>
      {% for src_uuid in sources %}
        {% set filtered_exchanges = exchanges | selectattr('source.owner.uuid', "equalto", src_uuid) | list %}
        {% for exchange in filtered_exchanges %}
          <tr>
            {% if loop.first %}
              <td rowspan="{{ filtered_exchanges | length }}">
                {{ linked_name_with_icon(exchange.source.owner) | safe }}
              </td>
            {% endif %}
            <td>
              {% if exchange.exchange_items %}
                {% if exchange.exchange_items | length > 1 %}
                  <ul>
                    {% for exi in exchange.exchange_items %}
                      <li><a href="#exi-{{ exi.uuid }}">{{ exi.name }}</a></li>
                    {% endfor %}
                  </ul>
                {% else %}
                  {% set exi = exchange.exchange_items[0] %}
                  <a href="#exi-{{ exi.uuid }}">{{ exi.name }}</a>
                {% endif %}
              {% else %}
                {{ linked_name_with_icon(exchange) | safe }}
              {% endif %}
            </td>
            <td>{{ linked_name_with_icon(exchange.target.owner) | safe }}</td>
          </tr>
        {% endfor %}
      {% endfor %}
    </tbody>
  </table>
{% endmacro %}

{% if partner_a_provides %}
  {{ describe_provided_functional_exchanges(partner_a_provides, partner_a, partner_b, partner_a_source_uuids) | safe }}
{% endif %}

{% if partner_b_provides %}
  {{ describe_provided_functional_exchanges(partner_b_provides, partner_b, partner_a, partner_b_source_uuids) | safe }}
{% endif %}

<h2>Interface Specification</h2>
<h3>Exchange Item (Message) Catalogue</h3>
<p>
  This section identifies Exchange Items / Messages used within the interface.
</p>
{% for exi in object.exchange_items %}
  <h4 id="exi-{{ exi.uuid }}">Exchange Item {{ linked_name(exi) }}</h4>
  {{ description(exi) | safe }}
  {% for el in exi.elements %}
    {{ add_class_dependencies(el.abstract_type, classes[direction]) }}
  {% endfor %}
{% endfor %}

{# {%- set classes = {} -%}
{%- set inserted = [] -%}
{% for direction, eis in exchange_items_by_direction.items() %}
    {{- classes.setdefault(direction, []) -}}
    {{ heading(4, model.by_uuid(direction[0]).name + " → " + model.by_uuid(direction[1]).name, session) }}
    {% for ei in eis | unique %}
        {{ heading(5, work_item_field(ei, "id") + " - " + ei.name, session) }}
        {{ insert_or_link(ei, inserted) }}
        {% for el in ei.elements %}
            {{ add_class_dependencies(el.abstract_type, classes[direction]) }}
        {% endfor %}
    {% endfor %}
{% endfor %} #}
{# {{ heading(3, "Message Description", session)}}
<p>This section provides a detailed description of each message used within the interface.</p>
{% for direction, clss in classes.items() %}
    {{ heading(4, model.by_uuid(direction[0]).name + " → " + model.by_uuid(direction[1]).name, session) }}
    {% for cl in clss | unique %}
        {{ heading(5, work_item_field(cl, "id") + " - " + cl.name, session) }}
        {{ insert_or_link(cl, inserted) }}
    {% endfor %}
{% endfor %} #}
