function createRow(table, cellName, items) {
    var tr = document.createElement('tr');
    var res = [];

    items.forEach(function(x, i) {
        if (x === undefined) {
            res.push(null);
            return;
        }

        var td = document.createElement(cellName);
        td.textContent = x;
        tr.appendChild(td);
        res.push(td);

        var colspan = 1;
        for (var n = i + 1; n < items.length; n++) {
            if (items[n] !== undefined) {
                break;
            }

            colspan += 1;
        }

        if (colspan > 1) {
            td.colSpan = colspan;
        }
    });

    table.appendChild(tr);

    return res;
}

function createVisualizationTable(data, cutoff = 0, sort = "") {
    var table = document.createElement('table');
    table.className = 'popup-table';

    var keys = Object.keys(data);
    if (sort === "number") {
        keys = keys.sort(function(a, b) {
            return data[b] - data[a];
        });
    } else {
        keys = keys.sort();
    }
    var items = keys.map(function(x) {
        return {key: x, parts: x.split('/'), value: data[x]};
    });
    var maxLength = items.reduce(function(a, b) {
        return Math.max(a, b.parts.length);
    }, 0);

    var cols = createRow(
        table,
        'th',
        [
            cutoff === 0 ? 'key' : 'record',
            cutoff === 0 ? 'value' : 'seconds'
        ]
    );
    cols[0].colSpan = maxLength;

    function arraysEqual(a, b) {
        return !(a < b || b < a);
    }

    var addLevel = function(level, parent, hide) {
        var matching = items.filter(function(x) {
            return x.parts[level] && !x.parts[level + 1] && arraysEqual(x.parts.slice(0, level), parent);
        });
        if (sort === "number") {
            matching = matching.sort(function(a, b) {
                return b.value - a.value;
            });
        } else {
            matching = matching.sort();
        }
        var othersTime = 0;
        var othersList = [];
        var othersRows = [];
        var childrenRows = [];
        matching.forEach(function(x) {
            var visible = (cutoff === 0 && !hide) || (x.value >= cutoff && !hide);

            var cells = [];
            for (var i = 0; i < maxLength; i++) {
                cells.push(x.parts[i]);
            }
            cells.push(cutoff === 0 ? x.value : x.value.toFixed(3));
            var cols = createRow(table, 'td', cells);
            for (i = 0; i < level; i++) {
                cols[i].className = 'muted';
            }

            var tr = cols[0].parentNode;
            if (!visible) {
                tr.classList.add("hidden");
            }

            if (cutoff === 0 || x.value >= cutoff) {
                childrenRows.push(tr);
            } else {
                othersTime += x.value;
                othersList.push(x.parts[level]);
                othersRows.push(tr);
            }

            var children = addLevel(level + 1, parent.concat([x.parts[level]]), true);
            if (children.length > 0) {
                var cell = cols[level];
                var onclick = function() {
                    cell.classList.remove("link");
                    cell.removeEventListener("click", onclick);
                    children.forEach(function(x) {
                        x.classList.remove("hidden");
                    });
                };
                cell.classList.add("link");
                cell.addEventListener("click", onclick);
            }
        });

        if (othersTime > 0) {
            var cells = [];
            for (var i = 0; i < maxLength; i++) {
                cells.push(parent[i]);
            }
            cells.push(othersTime.toFixed(3));
            cells[level] = 'others';
            var cols = createRow(table, 'td', cells);
            for (i = 0; i < level; i++) {
                cols[i].className = 'muted';
            }

            var cell = cols[level];
            var tr = cell.parentNode;
            var onclick = function() {
                tr.classList.add("hidden");
                cell.classList.remove("link");
                cell.removeEventListener("click", onclick);
                othersRows.forEach(function(x) {
                    x.classList.remove("hidden");
                });
            };

            cell.title = othersList.join(", ");
            cell.classList.add("link");
            cell.addEventListener("click", onclick);

            if (hide) {
                tr.classList.add("hidden");
            }

            childrenRows.push(tr);
        }

        return childrenRows;
    };

    addLevel(0, []);

    return table;
}

function showProfile(path, cutoff = 0.05) {
    requestGet(path, {}, function(data) {
        data.records['total'] = data.total;
        const table = createVisualizationTable(data.records, cutoff, "number");
        popup(table);
    });
}