{% extends "issues/base.html" %}
{% load static %}
{% load stricter_templates %}
{% load issues %}

{% block tab_content %}

{% if not exceptions %}
    {# event-nav only #}
    <div class="flex">
        <div class="overflow-hidden">
            <div class="italic">{{ event.server_side_timestamp|date:"j M G:i T" }} (Event {{ event.ingest_order }} of {{ issue.event_count }})</div>
        </div>

        <div class="ml-auto flex-none">
            <div class="flex place-content-end">
                {% include "issues/_event_nav.html" %}
            </div>
        </div>
    </div>

    <div class="mt-6 mb-6 italic">
        No stacktrace available for this event.
    </div>
{% endif %}


{% for exception in exceptions %}

    <div class="flex">
        <div class="overflow-hidden">
            {% if forloop.counter0 == 0 %}
            <div class="italic">{{ event.server_side_timestamp|date:"j M G:i T" }} (Event {{ event.ingest_order }} of {{ issue.event_count }})</div>
            {% endif %}
            <h1 class="text-2xl font-bold {% if forloop.counter0 > 0 %}mt-4{% endif %} text-ellipsis whitespace-nowrap overflow-hidden">{{ exception.type }}</h1>
            <div class="text-lg mb-4 text-ellipsis whitespace-nowrap overflow-hidden">{{ exception.value }}</div>

        </div>
        {% if forloop.counter0 == 0 %}
        <div class="ml-auto flex-none">
            <div class="flex place-content-end">
                <button class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring" onclick="showAllFrames()">Show all</button>
                <button class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring" onclick="showInAppFrames()">Show in-app</button>
                <button class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring" onclick="showRaisingFrame()">Show raise</button>
                <button class="font-bold text-slate-500 border-slate-300 pl-4 pr-4 pb-1 pt-1 mr-2 border-2 rounded-md hover:bg-slate-200 active:ring" onclick="hideAllFrames()">Collapse all</button>

                {% include "issues/_event_nav.html" %}
            </div>
        </div>
        {% endif %}
    </div>

    {% for frame in exception.stacktrace.frames %}
        {% with frame=frame|pygmentize %}
        
        <div class="bg-white w-full font-mono"> {# per frame div #}
            {% if frame.raise_point %}<a name="raise"/>{% endif %}
            {% if frame.in_app %}<a name="in-app"/>{% endif %}
            {% if forloop.first and forloop.parentloop.first %}<a name="topp"/>{% endif %}

            <div class="flex pl-4 pt-2 pb-2 border-b-2 {% if forloop.first %}border-t-2{% endif %} bg-slate-100 border-slate-400 cursor-pointer" onclick="toggleFrameVisibility(this)"> {# per frame header div #}

                <div> {# filename, function, lineno #}
                    {% if frame.in_app %}
                        <span class="font-bold">{{ frame.filename }}</span>{% if frame.function %} in <span class="font-bold">{{ frame.function }}</span>{% endif %}{% if frame.lineno %} line <span class="font-bold">{{ frame.lineno }}</span>{% endif %}.
                    {% else %}
                        <span class="italic">{{ frame.filename }}{% if frame.function %} in {{ frame.function }}{% endif %}{% if frame.lineno%} line {{ frame.lineno }}{% endif %}.</span>
                    {% endif %}
                </div>

                <div class="ml-auto pr-4">{# indicator for frame's position in stacktrace #}
                    {% if stack_of_plates and forloop.first or not stack_of_plates and forloop.last %}
                        {% if stack_of_plates and forloop.parentloop.first or not stack_of_plates and forloop.parentloop.last %}
                            <span class="bg-slate-200 pl-2 pr-2 pt-1 pb-1 rounded-md whitespace-nowrap">raise {{ exception.type }}</span>
                        {% else %}
                            <span class="bg-slate-200 pl-2 pr-2 pt-1 pb-1 rounded-md whitespace-nowrap">raise {{ exception.type }} (handled)</span>
                        {% endif %}
                    {% elif stack_of_plates and forloop.last or not stack_of_plates and forloop.first %} {# strictly speaking, not actually "else", but to avoid clutter we hide 'outermost' info when this is also the raise-point #}
                        {% if stack_of_plates and forloop.parentloop.first or not stack_of_plates and forloop.parentloop.last %}
                            <span class="bg-slate-200 pl-2 pr-2 pt-1 pb-1 rounded-md whitespace-nowrap">→ begin</span>
                        {% else %}
                            {% comment %}I find it (quite too) hard to come up with a good name for this type of frame that is both short and clear. Thoughts so fare were:
                            * try...
                            * start try
                            * start failing try (handled)
                            * "begin handled" ()
                            * "begin handled" {{ exception.type }}
                            * "outermost handled"
                            * "divergence w/ main exception"
                            * first unique frame
                            {% endcomment %}
                            <span class="bg-slate-200 pl-2 pr-2 pt-1 pb-1 rounded-md whitespace-nowrap">try…</span>
                        {% endif %}

                    {% endif %}
                </div>

                <div class="pr-4">{# chevron #}
                    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-5 h-5 js-chevron transition-all {% if frame.raise_point %}rotate-180{% endif %}">
                        <path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd" />
                    </svg>
                </div>
            </div> {# per frame header div #}

            <div class="js-frame-details {% if frame.in_app %}js-in-app{% endif %} border-slate-400 overflow-hidden transition-all {% if stack_of_plates and forloop.parentloop.first and forloop.first or not stack_of_plates and forloop.parentloop.last and forloop.last %}js-raising-frame{% endif %}" 
                {% if not frame.raise_point %}data-collapsed="true" style="height: 0px"{% endif %}> {# collapsable part #}

                <div class="pl-6 pr-6 {% if not forloop.last %}border-b-2 border-slate-400{% endif %}">{# convience div for padding & border; the border is basically the top-border of the next header #}
                    {% if "context_line" in frame and frame.context_line is not None %}
                    <div class="bg-slate-50 syntax-coloring mt-6 mb-6">{# code listing #}
                        {# the spread-out pX-6 in this code is intentional to ensure the padding is visible when scrolling to the right, and not visible when scrolling is possible (i.e. the text is cut-off awkwardly to hint at scrolling #}
                        <ol class="list-decimal overflow-x-auto list-inside pt-6 pb-6 {% if frame|firstlineno is None %}list-none{% endif %}" start="{{ frame|firstlineno }}">
                        {% for line in frame.pre_context %}<li class="pl-6"><div class="whitespace-pre w-full inline pr-6">{{ line }} {# leave space to avoid collapse #}</div></li>{% endfor %}
                        {# the gradient is a workaround, because I can't get a full-width elem going here inside the overflow #}
                        {# when some other line is overflowing. Using the gradient hides this fact (it happens to also look good) #}
                        <li class="pl-6 bg-gradient-to-r from-slate-300 font-bold w-full"><div class="whitespace-pre w-full inline pr-6">{{ frame.context_line }} {# leave space to avoid collapse #}</div></li>
                        {% for line in frame.post_context %}<li class="pl-6"><div class="whitespace-pre w-full inline pr-6">{{ line }} {# leave space to avoid collapse #}</div></li>{% endfor %}
                        </ol>
                    </div>
                    {% endif %}

                    {% if frame.vars %}
                    <div class="mt-4 mb-6">{# variables #}
                        <div class="flex">
                            <div class="w-1/4 pt-2 font-bold border-b-2 border-slate-500 pl-4">Variable</div>
                            <div class="w-3/4 pt-2 font-bold border-b-2 border-slate-500 pr-4">Value</div>
                        </div>
                        {% for var, value in frame.vars|items %}
                        <div class="flex">
                            <div class="w-1/4 pl-4 {% if not forloop.last %}border-b-2 border-dotted border-slate-300{% endif %}">{{ var }}</div>
                            <div class="w-3/4 pr-4 {% if not forloop.last %} border-b-2 border-dotted border-slate-300{% endif %}">{{ value }}</div>
                        </div>
                        {% endfor %}
                    </div>
                    {% endif %}

                    {% if "context_line" not in frame or frame.context_line is None %}{% if not frame.vars %}{# nested ifs as a subsitute for brackets-in-templates #}
                    <div class="mt-6 mb-6 italic">
                        No code context or variables available for this frame.
                    </div>
                    {% endif %}{% endif %}

                </div>

            </div> {# collapsable part #}

        </div> {# per frame div #}

        {% endwith %}
    {% endfor %} {# frame #}
    {# </div> #} {# per-exception div in the multi-exception case #}

    {% if not forloop.last %}
        {% if not stack_of_plates %}
            <div class="italic pt-4">During handling of the above exception another exception occurred or was intentionally reraised:</div>
            {# note: the above is specific to Python. We cannot distinguish between Python's 2 types of chained exceptions because the info is not sent by the client #}
            {# we could try to infer this from the stacktrace, but parsing potentially arbitrarily formatted partial code is brittle #}
        {% else %}
            <div class="italic pt-4">The above exception was caused by or intentially reraised during the handling of the following exception:</div>
        {% endif %}
    {% endif %}

{% endfor %} {# for exception in exceptions #}

{% endblock %}

{% block extra_js %}
    <script src="{% static 'js/issue_stacktrace.js' %}"></script>
{% endblock %}
