<ol class="breadcrumb">
    <li class="breadcrumb-item">{{t "coverage-page-title" }}</li>
</ol>

<div>
    <img src="./images/coverage-badge-documentation.svg">
</div>

<div class="coverage-summary" data-coverage-summary></div>

<div class="coverage-filter">
    <input type="text"
        class="coverage-filter-input"
        placeholder="Filter entities..."
        aria-label="Filter coverage results"
        data-coverage-filter>
    <button type="button"
        class="coverage-filter-clear"
        aria-label="Clear filter"
        data-coverage-filter-clear>&times;</button>
</div>

<table class="table table-bordered coverage" id="coverage-table">
    <thead class="coverage-header">
        <tr>
            <th>{{t "file" }}</th>
            <th>{{t "type" }}</th>
            <th>{{t "identifier" }}</th>
            <th style="text-align:right" class="statements" data-sort-default>{{t "statements" }}</th>
        </tr>
    </thead>
    <tbody>
        {{#each files}}
        <tr class="{{status}}">
            <td>
                <!-- miscellaneous -->
                {{#if linksubtype}}
                    {{#ifEqualString type 'type alias'}}
                        <a href="./{{linktype}}/{{linksubtype}}es.html#{{name}}">{{filePath}}</a>
                    {{else}}
                        <a href="./{{linktype}}/{{linksubtype}}s.html#{{name}}">{{filePath}}</a>
                    {{/ifEqualString}}
                {{else}}
                    {{#ifEqualString linktype 'entity'}}
                        <a href="./entities/{{name}}.html">{{filePath}}</a>
                    {{else}}
                        <a href="./{{linktype}}s/{{name}}.html">{{filePath}}</a>
                    {{/ifEqualString}}
                {{/if}}
            </td>
            <td>{{type}}</td>
            <td>{{name}}</td>
            <td align="right" data-sort="{{coveragePercent}}">
                <span class="coverage-percent">{{coveragePercent}} %</span>
                <span class="coverage-count">({{coverageCount}})</span>
            </td>
        </tr>
        {{/each}}
    </tbody>
</table>

<script src="{{relativeURL data.depth }}js/libs/tablesort.min.js"></script>
<script src="{{relativeURL data.depth }}js/libs/tablesort.number.min.js"></script>
<script>
    new Tablesort(document.getElementById('coverage-table'));

    (function () {
        var table = document.getElementById('coverage-table');
        if (!table) {
            return;
        }

        var tableBody = table.querySelector('tbody');
        if (!tableBody) {
            return;
        }

        var rows = Array.prototype.slice.call(tableBody.querySelectorAll('tr'));
        var summaryContainer = document.querySelector('[data-coverage-summary]');
        var filterInput = document.querySelector('[data-coverage-filter]');
        var filterClearButton = document.querySelector('[data-coverage-filter-clear]');

        function toPercent(value, total) {
            if (!total) {
                return 0;
            }
            return Math.round((value / total) * 100);
        }

        function getRowCoverageBucket(row) {
            var className = (row.className || '').toLowerCase();
            if (className.indexOf('low') !== -1) {
                return 'undocumented';
            }
            if (className.indexOf('medium') !== -1) {
                return 'partial';
            }
            if (className.indexOf('very-good') !== -1 || className.indexOf('good') !== -1) {
                return 'documented';
            }
            return 'partial';
        }

        function getCoverageStats() {
            var documented = 0;
            var partial = 0;
            var undocumented = 0;

            rows.forEach(function (row) {
                var bucket = getRowCoverageBucket(row);
                if (bucket === 'documented') {
                    documented += 1;
                } else if (bucket === 'partial') {
                    partial += 1;
                } else {
                    undocumented += 1;
                }
            });

            var total = rows.length;
            var totalCoveragePercent = rows.reduce(function (sum, row) {
                var scoreCell = row.querySelector('td[data-sort]');
                var rowScore = scoreCell ? parseFloat(scoreCell.getAttribute('data-sort') || '0') : 0;
                return sum + (isNaN(rowScore) ? 0 : rowScore);
            }, 0);
            var score = total ? Math.floor(totalCoveragePercent / total) : 0;

            return {
                total: total,
                documented: documented,
                partial: partial,
                undocumented: undocumented,
                score: score
            };
        }

        function buildDonutSegment(title, color, count, total, offset, circumference) {
            var percent = toPercent(count, total);
            if (!count) {
                return '';
            }

            var arcLength = (count / total) * circumference;
            var remaining = circumference - arcLength;

            return '<circle cx="60" cy="60" r="50" fill="none" stroke="' + color + '" stroke-width="10" ' +
                'style="stroke-dasharray: ' + arcLength + ', ' + remaining + '; stroke-dashoffset: ' + (-offset) + ';" ' +
                'transform="rotate(-90 60 60)" class="coverage-donut-segment">' +
                '<title>' + title + ': ' + count + ' (' + percent + '%)</title>' +
                '</circle>';
        }

        function renderSummary(stats) {
            if (!summaryContainer) {
                return;
            }

            var total = stats.total;
            var documentedPercent = toPercent(stats.documented, total);
            var partialPercent = toPercent(stats.partial, total);
            var undocumentedPercent = toPercent(stats.undocumented, total);
            var circumference = 2 * Math.PI * 50;
            var offset = 0;

            var documentedSegment = buildDonutSegment('Documented', '#4dc71f', stats.documented, total, offset, circumference);
            offset += total ? (stats.documented / total) * circumference : 0;

            var partialSegment = buildDonutSegment('Partial', '#dab226', stats.partial, total, offset, circumference);
            offset += total ? (stats.partial / total) * circumference : 0;

            var undocumentedSegment = buildDonutSegment('Undocumented', '#d8624c', stats.undocumented, total, offset, circumference);

            summaryContainer.innerHTML =
                '<svg viewBox="0 0 120 120" class="coverage-donut" role="img" aria-label="Documentation coverage: ' + stats.score + '%">' +
                    '<title>Documentation coverage: ' + stats.score + '%</title>' +
                    '<desc>' + stats.documented + ' documented, ' + stats.partial + ' partial, ' + stats.undocumented + ' undocumented of ' + stats.total + ' entities</desc>' +
                    '<circle cx="60" cy="60" r="50" fill="none" stroke="var(--bs-border-color, #dee2e6)" stroke-width="10" class="coverage-donut-ring"></circle>' +
                    documentedSegment +
                    partialSegment +
                    undocumentedSegment +
                    '<text x="60" y="60" text-anchor="middle" dominant-baseline="central" class="coverage-donut-pct">' + stats.score + '%</text>' +
                '</svg>' +
                '<div class="coverage-stats">' +
                    '<div>' +
                        '<div class="coverage-stat-value">' + stats.total + '</div>' +
                        '<div class="coverage-stat-label">Total</div>' +
                        '<div class="coverage-stat-sub">' + stats.total + ' entities</div>' +
                    '</div>' +
                    '<div>' +
                        '<div class="coverage-stat-value coverage-stat-value--documented">' + stats.documented + '</div>' +
                        '<div class="coverage-stat-label">Documented</div>' +
                        '<div class="coverage-stat-sub">' + documentedPercent + '%</div>' +
                    '</div>' +
                    '<div>' +
                        '<div class="coverage-stat-value coverage-stat-value--partial">' + stats.partial + '</div>' +
                        '<div class="coverage-stat-label">Partial</div>' +
                        '<div class="coverage-stat-sub">' + partialPercent + '%</div>' +
                    '</div>' +
                    '<div>' +
                        '<div class="coverage-stat-value coverage-stat-value--undocumented">' + stats.undocumented + '</div>' +
                        '<div class="coverage-stat-label">Undocumented</div>' +
                        '<div class="coverage-stat-sub">' + undocumentedPercent + '%</div>' +
                    '</div>' +
                '</div>';
        }

        function applyFilter() {
            if (!filterInput) {
                return;
            }

            var query = filterInput.value.toLowerCase().trim();
            rows.forEach(function (row) {
                var text = (row.textContent || '').toLowerCase();
                row.style.display = query.length === 0 || text.indexOf(query) !== -1 ? '' : 'none';
            });

            if (filterClearButton) {
                filterClearButton.classList.toggle('is-visible', query.length > 0);
            }
        }

        if (filterInput) {
            filterInput.addEventListener('input', applyFilter);
            filterInput.addEventListener('keydown', function (event) {
                if (event.key === 'Escape') {
                    filterInput.value = '';
                    applyFilter();
                }
            });
        }

        if (filterClearButton) {
            filterClearButton.addEventListener('click', function () {
                if (filterInput) {
                    filterInput.value = '';
                    applyFilter();
                    filterInput.focus();
                }
            });
        }

        renderSummary(getCoverageStats());
        applyFilter();
    })();
</script>
