<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <title>Linux s2idle Power Report</title>
    <style>
        h1 {
            color: #00b0f0;
            font-family: sans-serif;
            font-size: 42pt;
        }

        h2 {
            font-size: 15pt;
            font-family: sans-serif;
            color: #00b0f0;
            margin-top: 2em;
            margin-bottom: 0em;
            letter-spacing: 0.08em;
        }

        h3,
        h4,
        h5 {
            font-family: sans-serif;
            margin-top: 1em;
            margin-bottom: 0em;
            letter-spacing: 0.08em;
        }

        body {

            font-family: sans-serif;
            letter-spacing: 0.02em;
            background-color: #ffffff;
            color: #000000;
            margin: 2em auto;
            max-width: 1200px;
            padding: 0 2em;

        }

        table,
        th,
        td {
            border: 1px solid #ddd;
            border-collapse: collapse;
            table-layout: fixed;
            font-family: sans-serif;
            letter-spacing: 0.02em;
            color: #000000;
            text-align: left;
            padding: 8px;
        }

        th {
            background-color: #f8f9fa;
            position: sticky;
            top: 0;
            z-index: 10;
        }

        tr:not(.row-low):not(.row-neutral):not(.row-high):nth-child(even) {
            background-color: #f9f9f9;
        }

        tr:hover {
            background-color: #f2f2f2 !important;
        }

        #prereqdebugdata > tbody > tr:hover,
        #cycledata > tbody > tr:hover,
        #failuredata > tbody > tr:hover,
        #debugdata > tbody > tr:hover,
        #prereqdebugdata > tr:hover,
        #cycledata > tr:hover,
        #failuredata > tr:hover,
        #debugdata > tr:hover {
            background-color: transparent !important;
        }

        .○ {
            font-family: "Fira Code", monospace;
            color: #000000;
        }

        .❌ {
            color: #ff0000;
            font-family: "Fira Code", monospace;
        }

        .🚦 {
            color: #a4a100;
            font-family: "Fira Code", monospace;
        }

        .🦟 {
            color: #848484;
            font-family: "Fira Code", monospace;
        }

        .hidden-by-default {
            display: none;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .collapsible-wrapper {
            overflow: hidden;
            max-height: 0;
            opacity: 0;
            transition: max-height 0.4s ease-out, opacity 0.3s ease;
        }

        .collapsible-wrapper.expanded {
            max-height: 2000px; /* Large enough to hold table */
            opacity: 1;
        }

        .hide-borders {
            border: 0px;
            border-collapse: collapse;
        }

        .row-disabled {
            display: none;
            opacity: 0;
        }

        @keyframes fadeIn {
            from { opacity: 0; }
            to { opacity: 1; }
        }

        .row-active {
            display: table-row !important;
            animation: fadeIn 0.5s ease forwards;
        }

        .arrow {
            cursor: pointer;
            display: inline-block;
        }

        .arrow::before {
            content: "\23f5";
            margin-right: 5px;
        }

        .arrow-expanded::before {
            content: "\23F7";
        }

        @media (prefers-color-scheme: dark) {
            body {
                background-color: #121212;
                color: #e0e0e0;
            }
            table, th, td {
                border-color: #333;
                color: #e0e0e0;
            }
            th {
                background-color: #1e1e1e;
            }
            tr:not(.row-low):not(.row-neutral):not(.row-high):nth-child(even) {
                background-color: #1a1a1a;
            }
            tr:hover {
                background-color: #2a2a2a !important;
            }
            .row-low { background-color: #1b4d1b; }
            .row-low:hover { background-color: #266b26; }
            .row-neutral { background-color: #333; }
            .row-neutral:hover { background-color: #444; }
            .row-high { background-color: #611a14; }
            .row-high:hover { background-color: #8a251d; }
            .○ { color: #e0e0e0; }
            .🦟 { color: #aaa; }
            #prereqdebugdata > tbody > tr:hover,
            #cycledata > tbody > tr:hover,
            #failuredata > tbody > tr:hover,
            #debugdata > tbody > tr:hover,
            #prereqdebugdata > tr:hover,
            #cycledata > tr:hover,
            #failuredata > tr:hover,
            #debugdata > tr:hover {
                background-color: transparent !important;
            }
        }
    </style>
</head>

<body>
    <script>
        function select_changed(selector, row) {
            var x = document.getElementById(selector).value;
            var rows = document.querySelectorAll(row + " tr.row-disabled");
            for (var i = 0; i < rows.length; i++) {
                rows[i].classList.remove("row-active");
            }
            if (x != "0") {
                var target = document.querySelector(row + x);
                if (target) {
                    target.classList.add("row-active");
                }
                if (row == row + x)
                    document.getElementById(selector).value = 0;
            }
        }
        function cycle_data_changed() {
            select_changed("cycles", "#cycledata")
        }

        function failure_data_changed() {
            select_changed("failures", "#failuredata")
        }

        function debug_data_changed() {
            select_changed("debug", "#debugdata")
            var label = document.getElementById("debug_label");
            if (document.getElementById("debug").value != "0") {
                label.style.display = "block";
                setTimeout(() => label.style.opacity = "1", 10);
            } else {
                label.style.opacity = "0";
                setTimeout(() => label.style.display = "none", 300);
            }
        }

        function prereq_debug_data_changed() {
            var wrapper = document.getElementById("prereqdebugdata-wrapper");
            var arrow = document.getElementById("prereqdata-arrow");
            if (wrapper.classList.contains("expanded")) {
                wrapper.classList.remove("expanded");
                arrow.classList.remove("arrow-expanded");
            } else {
                wrapper.classList.add("expanded");
                arrow.classList.add("arrow-expanded");
            }
        }

        function parseTimeToSeconds(timeString) {
            var timeParts = timeString.split(":");
            var hours = parseInt(timeParts[0]);
            var minutes = parseInt(timeParts[1]);
            var seconds = parseInt(timeParts[2]);
            return (hours * 3600) + (minutes * 60) + seconds;
        }

        function pick_data_for_cycle(num) {
            //show cycles messages for this cycle
            document.getElementById("cycles").selectedIndex = num + 1;
            cycle_data_changed();
            {% if failures %}
            //show failures messages for this cycle
            document.getElementById("failures").value = num + 1;
            failure_data_changed();
            {% endif %}
            {% if debug_data %}
            //show debug data for this cycle
            document.getElementById("debug").selectedIndex = num + 1;
            debug_data_changed();
            {% endif %}
        }

        function summary_data_changed(ev) {
            var table = document.getElementById("summary");
            const start_select = document.getElementById('start_select');
            const end_select = document.getElementById('end_select');
            
            if (!start_select || !end_select) return;

            var start = parseInt(start_select.value);
            var end = parseInt(end_select.value);

            // reset end if start was picked bigger than end
            if (start > end) {
                end_select.selectedIndex = start;
                end = start;
            }

            var min_duration = 0;
            if (document.getElementById('med_duration').checked)
                min_duration = document.getElementById("med_duration").value;
            else if (document.getElementById('min_duration').checked)
                min_duration = document.getElementById("min_duration").value;

            // show all rows between start and end
            var rows = table.tBodies[0].rows;
            for (var i = 0; i < rows.length; i++) {
                var row = rows[i];
                var index_cell = row.cells[0];
                if (!index_cell) continue;
                
                var index = parseInt(index_cell.textContent);
                var duration_cell = row.cells[2];
                var row_duration = duration_cell ? parseTimeToSeconds(duration_cell.textContent) : 0;

                if (row_duration >= min_duration &&
                    index >= start && index <= end) {
                    row.style.display = "";
                } else {
                    row.style.display = "none";
                }
            }

            // reset other tables if we now show more than one cycle
            if (end - start > 0) {
                var cycles_select = document.getElementById("cycles");
                if (cycles_select) {
                    cycles_select.selectedIndex = 0;
                    cycle_data_changed();
                }
                {% if failures %}
                var failures_select = document.getElementById("failures");
                if (failures_select) {
                    failures_select.value = 0;
                    failure_data_changed();
                }
                {% endif %}
                {% if debug_data %}
                var debug_select = document.getElementById("debug");
                if (debug_select) {
                    debug_select.selectedIndex = 0;
                    debug_data_changed();
                }
                {% endif %}
            } else if (start == end) {
                pick_data_for_cycle(start);
            }
        }

        function populate_summary_selectors() {
            const table = document.getElementById('summary');
            const start_select = document.getElementById('start_select');
            const end_select = document.getElementById('end_select');
            
            if (!start_select || !end_select || !table || !table.tBodies || !table.tBodies[0]) return;

            var rows = table.tBodies[0].rows;
            for (let i = 0; i < rows.length; i++) {
                const start_option = document.createElement('option');
                const end_option = document.createElement('option');
                var columns = rows[i].getElementsByTagName("td");

                //Populate all start/end selector values
                start_option.text = `Cycle ${i}`;
                start_option.value = i;
                end_option.text = `Cycle ${i}`;
                end_option.value = i;
                start_select.add(start_option);
                end_select.add(end_option);

                if (columns.length > 2) {
                    //apply coloring to hardware sleep
                    if (parseFloat(columns[2].innerHTML) < 85)
                        rows[i].className = "row-high";
                }
            }

            // Pick the end selector for last column
            end_select.selectedIndex = rows.length - 1;

            summary_data_changed(event);

            // if we only have one cycle then pick it
            if (rows.length == 1) {
                pick_summary_cycle(0)
            }
        }

        function pick_summary_cycle(num) {
            document.getElementById('start_select').selectedIndex = num;
            document.getElementById('end_select').selectedIndex = num;
            summary_data_changed(event);
            pick_data_for_cycle(num);
        }

        function reset_clicked() {
            const table = document.getElementById('summary');
            var rows = table.tBodies[0].rows;
            document.getElementById('start_select').selectedIndex = 0;
            document.getElementById('end_select').selectedIndex = rows.length - 1;
            document.getElementById('all_time').checked = true;
            summary_data_changed(event);
        }

        window.addEventListener('load', populate_summary_selectors);
    </script>
    <h1>Linux s2idle Power Report</h1>
    <p>s2idle report created {{ date }} using amd-s2idle {{version}}</p>
    {% if prereq %}
    <table class="hide-borders">
        {% for obj in prereq %}
        <TR>
            <TD>{{obj.symbol}}</TD>
            <TD>{{obj.text}}</TD>
        </TR>
        {% endfor %}
    </table>
    {% endif %}
    {% if prereq_debug_data %}
    <h3>
        <span id="prereqdata-arrow" onclick="prereq_debug_data_changed()" class="arrow">Prerequisites</span>
    </h3>
    <div id="prereqdebugdata-wrapper" class="collapsible-wrapper">
        <table id="prereqdebugdata" class="hide-borders">
            {% for obj in prereq_debug_data %}
            <TR>
                <TD>
                    <pre>{{obj.data}}</pre>
                </TD>
            </TR>
            {% endfor %}
        </table>
    </div>
    {% endif %}
    <h2>Summary</h2>
    {% if battery_svg %}
    <h3>Battery</h3>
    {{ battery_svg | safe }}
    {% endif %}
    {% if hwsleep_svg %}
    <h3>Low power state residency</h3>
    {{ hwsleep_svg | safe }}
    {% endif %}
    {% if cycle_data|length > 1 %}
    <h3>Cycle data</h3>
    <p>Choose a single cycle to see messages and data for that cycle.</p>
    <button type="button" onclick="reset_clicked()">Reset</button>
    <h4>Filter cycle range</h4>
    <select id="start_select" onchange="summary_data_changed(event)"></select>
    and
    <select id="end_select" onchange="summary_data_changed(event)"></select>
    <h4>Filter minimum session length</h4>
    <input type="radio" name="session1" id="all_time" value="all_time" onchange="summary_data_changed(event)"
        checked="" />
    <label>All</label>
    <input type="radio" name="session1" id="med_duration" value="600" onchange="summary_data_changed(event)" />
    <label>&gt;10 min</label>
    <input type="radio" name="session1" id="min_duration" value="60" onchange="summary_data_changed(event)" />
    <label>&gt;1 min</label>
    {% else %}
    <select id="start_select" class="hidden-by-default"></select>
    <select id="end_select" class="hidden-by-default"></select>
    <input type="radio" name="session1" id="all_time" value="all_time" checked="" class="hidden-by-default" />
    <input type="radio" name="session1" id="med_duration" value="600" class="hidden-by-default" />
    <input type="radio" name="session1" id="min_duration" value="60" class="hidden-by-default" />
    {% endif %}
    {{ summary }}
    {% if cycle_data %}
    <p><label for="cycle" class="hidden-by-default">Choose a cycle:</label>
        <select id="cycles" onchange="cycle_data_changed()" class="hidden-by-default">
            <option value="0">Disabled</option>
            {% for obj in cycle_data %}
            <option value="{{obj.cycle_num + 1}}">Cycle {{obj.cycle_num}}</option>
            {% endfor %}
        </select>
    </p>
    <table id="cycledata" class="hide-borders">
        {% for obj in cycle_data %}
        <TR class="row-disabled" id="cycledata{{obj.cycle_num + 1}}">
            <TD>{{obj.data}}</TD>
        </TR>
        {% endfor %}
    </table>
    {% endif %}
    {% if failures %}
    <p><label for="failure" class="hidden-by-default">Choose a cycle:</label>
        <select id="failures" onchange="failure_data_changed()" class="hidden-by-default">
            <option value="0">Disabled</option>
            {% for obj in failures %}
            <option value="{{obj.cycle_num + 1}}">Cycle {{obj.cycle_num}}</option>
            {% endfor %}
        </select>
    </p>
    <table id="failuredata" class="hide-borders">
        {% for obj in failures %}
        <TR class="row-disabled" id="failuredata{{obj.cycle_num + 1}}">
            <TD>{{obj.problem}}</TD>
            <TD>{{obj.data}}</TD>
        </TR>
        {% endfor %}
    </table>
    {% endif %}
    {% if debug_data %}
    <h3 id="debug_label" style="display:none; transition: opacity 0.3s ease; opacity: 0;">Debugging 🦟</h3>
    <p><label for="debug" class="hidden-by-default">Choose a cycle:</label>
        <select id="debug" onchange="debug_data_changed()" class="hidden-by-default">
            <option value="0">Disabled</option>
            {% for obj in debug_data %}
            <option value="{{obj.cycle_num + 1}}">Cycle {{obj.cycle_num}}</option>
            {% endfor %}
        </select>
    </p>
    <table id="debugdata" class="hide-borders">
        {% for obj in debug_data %}
        <TR class="row-disabled" id="debugdata{{obj.cycle_num + 1}}">
            <TD>
                {% for index in range(obj.messages | length) %}
                <div class="{{obj.priorities[index]}}">{{obj.messages[index]}}</div>
                {% endfor %}
            </TD>
        </TR>
        {% endfor %}
    </table>
    {% endif %}
</body>

</html>
