{#-
 # SPDX-FileCopyrightText: Copyright DB Netz AG and the capellambse contributors
 # SPDX-License-Identifier: Apache-2.0
-#}

{% set CATEGORIES = ["REQUIRED", "RECOMMENDED", "SUGGESTED"] -%}
{% set object_classes = [
  "SystemCapability",
  "SystemActor",
  "SystemComponent",
  "SystemFunction",
  "ComponentExchange",
  "FunctionalExchange"
] -%}
{% set results = results.by_class(*object_classes) -%}

{% macro show_compliance_score(results, align=None) -%}
  {% if results | count > 0 -%}
    {% set total = results | count -%}
    {% set passed = results.by_passed(True) | count -%}
    {% set score = (passed / total * 100) | round(1) -%}
    {% if score < 30 -%}
      {% set color = "#bc2604" -%}
    {% elif score < 70 -%}
      {% set color = "#ae930d" -%}
    {% else -%}
      {% set color = "#0a6600" -%}
    {% endif -%}
    <span style="color: {{color}}{% if align %}; float: {{align}}{% endif %}">
      {{score}}% <small>({{passed}} / {{total}})</small>
    </span>
    <div style="margin: 0; height: 5px; background: linear-gradient(to right, green {{score}}%, red {{score}}%)"></div>
  {% else -%}
    <span style="color: #ccc">not applicable</span>
    <div style="margin: 0; height: 5px; background: #ccc"></div>
  {% endif -%}
{% endmacro -%}

<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
  .small { font-size: 60%; }
  .rule-required { color: #ff4f26; }
  .rule-recommended { color: #039c08; }
  .rule-suggested { color: #17a3d4; }

/* General styles */
html, body {
  font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
  font-size: 16px;
  line-height: 1.5;
  color: #333;
}

body { margin: 1em; }

/* Hyperlink styles */
a {
  color: #0066cc;
  text-decoration: none;
  transition: color 0.3s ease;
}

a:hover {
  color: #004799;
  text-decoration: underline;
}

/* Table styles */
table {
  table-layout: fixed; /* This ensures that the table cells have fixed widths */
  width: 100%; /* Ensures the table takes up the full width of its container */
  border-collapse: separate;
  border-spacing: 0;
  margin-bottom: 1rem;
  border: 1px solid #ccc;
}

th, td {
  padding: 0.75rem;
  text-align: left;
  position: relative;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  min-width: 100px; /* You can adjust the minimum width to fit your needs */
  word-wrap: break-word; /* Breaks long words if they exceed the cell width */
  overflow-wrap: break-word; /* A more modern alternative to word-wrap */
}

thead th {
  background-color: #f2f2f2;
  position: sticky;
  top: 0;
  z-index: 10;
  font-weight: bold;
  text-transform: uppercase;
}

tbody th {
  background-color: #f2f2f2;
  position: sticky;
  left: 0;
  z-index: 5;
  border-right: 1px solid #ccc;
}

td ul {
  margin: 0;
  padding-left: 1em;
}

tr:nth-child(even) { background-color: #f8f8f8; }

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: stretch;
}

.container > table {
  flex-basis: 50%;
  max-width: 50%;
  box-sizing: border-box;
  padding-right: 10px;
}

.container > svg {
  flex-basis: 50%;
  max-width: 50%;
  box-sizing: border-box;
  padding-left: 10px;
}
</style>

<title>System Analysis Layer: Modelling Rules Compliance Report</title>
</head>
<body>
<h1>System Analysis Layer: Modeling Rules Compliance Report</h1>
<p>
  The report provides an assessment of adherence to Modeling Rules and Best Practices by the contents of the System Analysis model layer.
</p>

<h2>Assessment Summary</h2>
We reviewed <strong>{{ model.validation.search(*object_classes) | list | count }}</strong> model objects and found that overall compliance with the modelling rules is:<br>
{% for category in CATEGORIES -%}
  {% set category_results = results.by_category(category) -%}
  {% set total = category_results | count -%}
  {% set passed = category_results.by_passed(True) | count -%}
  {% set score = (passed / total * 100) | round(1) if total else 100 -%}
  {% if score < 30 -%}
    {% set color = "#bc2604" -%}
  {% elif score < 70 -%}
    {% set color = "#ae930d" -%}
  {% else -%}
    {% set color = "#0a6600" -%}
  {% endif -%}
  <span style="color: {{color}}">{{score}}%</span> <small>({{passed}} / {{total}})</small> for {{category}}
  {%- if loop.last %}.{% else %}; {% endif -%}
{% endfor %}

<table>
  <thead>
    <tr>
      <th rowspan="2">Reviewed objects</th>
      <th rowspan="2" width="90px">Total objects</th>
      <th colspan="{{ CATEGORIES | count }}">Compliance to applicable modeling rules</th>
    </tr>
    <tr>
      {% for category in CATEGORIES -%}
        <th>{{ category }}</th>
      {% endfor -%}
    </tr>
  </thead>
  <tbody>
    {% for obj_cls in object_classes %}<tr>
      {% set total = model.validation.search(obj_cls) | count %}
      <th><a href="#{{ obj_cls }}">{{ obj_cls }}</a></th>
      <td>{{ total }}</td>
      {% for category in CATEGORIES %}<td>
        {{ show_compliance_score(results.by_category(category).by_class(obj_cls)) }}
      </td>{% endfor %}
    </tr>{% endfor %}
  </tbody>
</table>

<h2>Object Compliance Analysis</h2>
<p>This section evaluates the selected objects' adherence to modeling rules. If an object needs additional work or has
  potential for improvement, we provide actionable suggestions to enhance its compliance.</p>

{% for obj_cls in object_classes %}
<h3 id="{{ obj_cls }}">{{ obj_cls }}</h3>
{% if not results.by_class(obj_cls) -%}
<p>No rules apply to {{ obj_cls }} objects or no objects of interest found in the selected layer.</p>
{% else -%}
{% for obj in results.by_class(obj_cls).by_passed(False).iter_objects() | sort(attribute="name") -%}
  {% if loop.first -%}
    <table>
      <thead>
        <tr>
          <th width="250px">{{ obj_cls }}</th>
          <th width="220px">Rule Compliance (%)</th>
          <th>Improvement Suggestions (Actions)</th>
        </tr>
      </thead>
      <tbody>
  {% endif -%}
  {% set categories = results.by_object(obj).by_passed(False) | map(attribute="rule.category") | sort(attribute="value") | unique | list -%}
  {% for category in categories -%}
    {% set cat_results = results.by_object(obj).by_category(category) -%}
    <tr>
      {% if loop.first -%}
        <th rowspan="{{ categories | count }}" id="{{ obj.uuid }}">{{ obj.name }}</th>
      {% endif -%}
      <td>
        <b class="rule-{{ category | lower }}">{{ category }}</b>:
        {{ show_compliance_score(cat_results, align="right") }}
      </td>
      <td>
        {% for rule in cat_results.by_passed(False).iter_rules() -%}
          {% if loop.first %}<ul>{% endif -%}
          <li><a href="#{{ rule.id }}">{{ rule.action }}</a></li>
          {% if loop.last %}</ul>{% endif -%}
        {% else -%}
          <em>No action required</em>
        {% endfor -%}
      </td>
    </tr>
  {% endfor -%}
  {% if loop.last -%}
      </tbody>
    </table>
  {% endif -%}
{% endfor -%}

{% set categories_of_interest = [] -%}
{% for category in CATEGORIES -%}
  {% set objects_of_interest = [] -%}
  {% for obj in objects if results.by_category(category).by_uuid(obj.uuid) and not results.by_category(category).by_value(False).by_uuid(obj.uuid) -%}
    {% set _ = objects_of_interest.append(obj) -%}
  {% endfor -%}
  {% if objects_of_interest | count > 0 -%}
    {% set _ = categories_of_interest.append([category, objects_of_interest]) -%}
  {% endif -%}
{% endfor -%}
{% for category in CATEGORIES if results.by_class(obj_cls).by_category(category) | count > 0 and results.by_class(obj_cls).by_category(category).iter_compliant_objects() | list | count > 0 %}
  {% if loop.first %}
  <p>These objects fully comply with at least one rule category:</p>
  {% endif %}
  {% set results_of_interest = results.by_class(obj_cls).by_category(category) -%}
  {% set compliant_objects = results_of_interest.iter_compliant_objects() | sort(attribute="name") -%}
  <p>
    All <strong>{{ results_of_interest.iter_rules() | list | count }}</strong>
    <strong class="rule-{{category|lower}}">{{category}}</strong> rules were met by the following {{ compliant_objects | count }} object(s):</b>
    {{ compliant_objects | join("; ", attribute="name")}}
  </p>
{% endfor %}
{% endif -%}
{% endfor -%}

<h2>Validation results by rule</h2>
<table>
<thead>
  <tr>
    <th width="160px">Rule ID
    <th>Definition
    <th width="100px">Passed
    <th>Failed
  <tbody>
    {% for rule in results.iter_rules() | sort(attribute="id") | sort(attribute="category.value") -%}
    {% set rule_results = results.by_rule(rule) -%}
    <tr>
      <th id="{{rule.id}}">
        {{rule.id}}<br>
        <span class="rule-{{rule.category.name|lower}}">{{rule.category.name}}</span>
        <p style="color:#999">Applies to: {{ rule.types | list | join(", ") }}</p>
      </th>
      <td>
        <strong>{{ rule.name }}</strong><br>
        {{ rule.rationale }}
        <p><b>Recommended action:</b><br>{{ rule.action }}</p>
      </td>
      <td>{{ show_compliance_score(rule_results) }}</td>
      <td>
        {% for result in rule_results | sort(attribute="object.name") if not result.passed -%}
          {% if loop.first %}<ul>{%- endif -%}
          <li><a href="#{{result.object.uuid}}">
            {{result.object.name|e}} <span class="small">({{result.object.uuid}})</span>
          </a></li>
          {% if loop.last %}</ul>{% endif -%}
        {% else -%}
          All {{ rule_results.iter_objects() | list | count}} object(s) comply to this rule
        {%- endfor %}
      </td>
    </tr>
    {%- endfor %}
  </tbody>
</table>

</body>
</html>
