{% extends '@WebProfiler/Profiler/layout.html.twig' %}

{% import _self as helper %}

{% set classnames = {
    'default': 'timeline-category-default',
    'section': 'timeline-category-section',
    'event_listener': 'timeline-category-event-listener',
    'template': 'timeline-category-template',
    'doctrine': 'timeline-category-doctrine',
    'messenger.middleware': 'timeline-category-messenger-middleware',
    'controller.argument_value_resolver': 'timeline-category-controller-argument-value-resolver',
} %}

{% block toolbar %}
    {% set has_time_events = collector.events|length > 0 %}
    {% set total_time = has_time_events ? '%.0f'|format(collector.duration) : 'n/a' %}
    {% set initialization_time = collector.events|length ? '%.0f'|format(collector.inittime) : 'n/a' %}
    {% set status_color = has_time_events and collector.duration > 1000 ? 'yellow' : '' %}

    {% set icon %}
        {{ include('@WebProfiler/Icon/time.svg') }}
        <span class="sf-toolbar-value">{{ total_time }}</span>
        <span class="sf-toolbar-label">ms</span>
    {% endset %}

    {% set text %}
        <div class="sf-toolbar-info-piece">
            <b>Total time</b>
            <span>{{ total_time }} ms</span>
        </div>
        <div class="sf-toolbar-info-piece">
            <b>Initialization time</b>
            <span>{{ initialization_time }} ms</span>
        </div>
    {% endset %}

    {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }}
{% endblock %}

{% block menu %}
    <span class="label">
        <span class="icon">{{ include('@WebProfiler/Icon/time.svg') }}</span>
        <strong>Performance</strong>
    </span>
{% endblock %}

{% block panel %}
    {% set has_time_events = collector.events|length > 0 %}
    <h2>Performance metrics</h2>

    <div class="metrics">
        <div class="metric">
            <span class="value">{{ '%.0f'|format(collector.duration) }} <span class="unit">ms</span></span>
            <span class="label">Total execution time</span>
        </div>

        <div class="metric">
            <span class="value">{{ '%.0f'|format(collector.inittime) }} <span class="unit">ms</span></span>
            <span class="label">Symfony initialization</span>
        </div>

        {% if profile.collectors.memory %}
            <div class="metric">
                <span class="value">{{ '%.2f'|format(profile.collectors.memory.memory / 1024 / 1024) }} <span class="unit">MB</span></span>
                <span class="label">Peak memory usage</span>
            </div>
        {% endif %}

        {% if profile.children|length > 0 %}
            <div class="metric-divider"></div>

            <div class="metric">
                <span class="value">{{ profile.children|length }}</span>
                <span class="label">Sub-Request{{ profile.children|length > 1 ? 's' }}</span>
            </div>

            {% if has_time_events %}
                {% set subrequests_time = 0 %}
                {% for child in profile.children %}
                    {% set subrequests_time = subrequests_time + child.getcollector('time').events.__section__.duration %}
                {% endfor %}
            {% else %}
                {% set subrequests_time = 'n/a' %}
            {% endif %}

            <div class="metric">
                <span class="value">{{ subrequests_time }} <span class="unit">ms</span></span>
                <span class="label">Sub-Request{{ profile.children|length > 1 ? 's' }} time</span>
            </div>
        {% endif %}
    </div>

    <h2>Execution timeline</h2>

    {% if not collector.isStopwatchInstalled() %}
        <div class="empty">
            <p>The Stopwatch component is not installed. If you want to see timing events, run: <code>composer require symfony/stopwatch</code>.</p>
        </div>
    {% elseif collector.events is empty %}
        <div class="empty">
            <p>No timing events have been recorded. Check that symfony/stopwatch is installed and debugging enabled in the kernel.</p>
        </div>
    {% else %}
        {{ block('panelContent') }}
    {% endif %}
{% endblock %}

{% block panelContent %}
    <form id="timeline-control" action="" method="get">
        <input type="hidden" name="panel" value="time">
        <label for="threshold">Threshold</label>
        <input type="number" name="threshold" id="threshold" value="1" min="0" placeholder="1.1"> ms
        <span class="help">(timeline only displays events with a duration longer than this threshold)</span>
    </form>

    {% if profile.parent %}
        <h3 class="dump-inline">
            Sub-Request {{ profiler_dump(profile.getcollector('request').requestattributes.get('_controller')) }}
            <small>
                {{ collector.events.__section__.duration }} ms
                <a class="newline" href="{{ path('_profiler', { token: profile.parent.token, panel: 'time' }) }}">Return to parent request</a>
            </small>
        </h3>
    {% elseif profile.children|length > 0 %}
        <h3>
            Main Request <small>{{ collector.events.__section__.duration }} ms</small>
        </h3>
    {% endif %}

    {{ helper.display_timeline(token, classnames, collector.events, collector.events.__section__.origin) }}

    {% if profile.children|length %}
        <p class="help">Note: sections with a striped background correspond to sub-requests.</p>

        <h3>Sub-requests <small>({{ profile.children|length }})</small></h3>

        {% for child in profile.children %}
            {% set events = child.getcollector('time').events %}
            <h4>
                <a href="{{ path('_profiler', { token: child.token, panel: 'time' }) }}">{{ child.getcollector('request').identifier }}</a>
                <small>{{ events.__section__.duration }} ms</small>
            </h4>

            {{ helper.display_timeline(child.token, classnames, events, collector.events.__section__.origin) }}
        {% endfor %}
    {% endif %}

<svg id="timeline-template" width="0" height="0">
  <defs>
    <pattern id="subrequest" class="timeline-subrequest-pattern" patternUnits="userSpaceOnUse" width="20" height="20" viewBox="0 0 40 40">
        <path d="M0 40L40 0H20L0 20M40 40V20L20 40"/>
    </pattern>
  </defs>
</svg>
<style type="text/css">
{% include '@WebProfiler/Collector/time.css.twig' with classnames %}
</style>
<script>
{% include '@WebProfiler/Collector/time.js' %}
</script>
{% endblock %}

{% macro dump_request_data(token, events, origin) %}
{% autoescape 'js' %}
{% from _self import dump_events %}
{
    id: "{{ token }}",
    left: {{ "%F"|format(events.__section__.origin - origin) }},
    end: "{{ '%F'|format(events.__section__.endtime) }}",
    events: [ {{ dump_events(events) }} ],
}
{% endautoescape %}
{% endmacro %}

{% macro dump_events(events) %}
{% autoescape 'js' %}
{% for name, event in events %}
{% if '__section__' != name %}
{
    name: "{{ name }}",
    category: "{{ event.category }}",
    origin: {{ "%F"|format(event.origin) }},
    starttime: {{ "%F"|format(event.starttime) }},
    endtime: {{ "%F"|format(event.endtime) }},
    duration: {{ "%F"|format(event.duration) }},
    memory: {{ "%.1F"|format(event.memory / 1024 / 1024) }},
    elements: {},
    periods: [
        {%- for period in event.periods -%}
        {
            start: {{ "%F"|format(period.starttime) }},
            end: {{ "%F"|format(period.endtime) }},
            duration: {{ "%F"|format(period.duration) }},
            elements: {}
        },
        {%- endfor -%}
    ],
},
{% endif %}
{% endfor %}
{% endautoescape %}
{% endmacro %}

{% macro display_timeline(token, classnames, events, origin) %}
{% import _self as helper %}
    <div class="sf-profiler-timeline">
        <div id="legend-{{ token }}" class="legends"></div>
        <svg id="timeline-{{ token }}" class="timeline-graph"></svg>
        <script>{% autoescape 'js' %}
            window.addEventListener('load', function onLoad() {
                new TimelineEngine(
                    new SvgRenderer(document.getElementById('timeline-{{ token }}')),
                    new Legend(document.getElementById('legend-{{ token }}'), {{ classnames|json_encode|raw }}),
                    document.getElementById('threshold'),
                    {{ helper.dump_request_data(token, events, origin) }}
                );
            });
        {% endautoescape %}</script>
    </div>
{% endmacro %}
