"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.collectTraces = exports.renderHierarchy = exports.renderStatus = exports.renderOne = exports.prettyPrint = exports.prettyPrintM = exports.dumpStr = exports.dumpFibers = exports.dump = void 0;
const Function_1 = require("../Function");
const IT = __importStar(require("../Iterable"));
const Option_1 = require("../Option");
const parse_ms_1 = require("../Utils/parse-ms");
const T = __importStar(require("./_internal/effect-api"));
const dump_1 = require("./dump");
const fiberName_1 = require("./fiberName");
function dump(fiber) {
    return T.map_(T.zipPar_(fiber.getRef(fiberName_1.fiberName), fiber.status), ({ tuple: [name, status] }) => (0, dump_1.FiberDump)(fiber.id, name, status));
}
exports.dump = dump;
function dumpFibers(fibers) {
    return T.forEach_(fibers, dump);
}
exports.dumpFibers = dumpFibers;
function dumpStr(fibers, withTrace) {
    const du = T.forEach_(fibers, dump);
    const now = T.succeedWith(() => new Date().getTime());
    return T.map_(T.zipWith_(du, now, Function_1.tuple), ([dumps, now]) => {
        const tree = renderHierarchy(dumps);
        const dumpStrings = withTrace ? collectTraces(dumps, now) : [];
        return IT.reduce_(dumpStrings, tree, (acc, v) => acc + "\n" + v);
    });
}
exports.dumpStr = dumpStr;
function prettyPrintM(dump) {
    return T.succeed(prettyPrint(dump, new Date().getTime()));
}
exports.prettyPrintM = prettyPrintM;
/**
 * @internal
 */
function prettyPrint(dump, now) {
    const { days, hours, milliseconds, minutes, seconds } = (0, parse_ms_1.parseMs)(now - dump.fiberId.startTimeMillis);
    const name = (0, Option_1.fold_)(dump.fiberName, (0, Function_1.constant)(""), (n) => `"${n}" `);
    const lifeMsg = (days === 0 ? "" : `${days}d`) +
        (days === 0 && hours === 0 ? "" : `${hours}h`) +
        (days === 0 && hours === 0 && minutes === 0 ? "" : `${minutes}m`) +
        (days === 0 && hours === 0 && minutes === 0 && seconds === 0 ? "" : `${seconds}s`) +
        `${milliseconds}ms`;
    const waitMsg = (function (status) {
        switch (status._tag) {
            case "Suspended":
                return status.blockingOn.length > 0
                    ? `waiting on ` + status.blockingOn.map((id) => `${id.seqNumber}`).join(", ")
                    : "";
            default:
                return "";
        }
    })(dump.status);
    const statMsg = renderStatus(dump.status);
    return [
        `${name}#${dump.fiberId.seqNumber} (${lifeMsg}) ${waitMsg}`,
        `   Status: ${statMsg}`
    ].join("\n");
}
exports.prettyPrint = prettyPrint;
/**
 * @internal
 */
function renderOne(tree) {
    const prefix = "";
    const name = (0, Option_1.fold_)(tree.fiberName, (0, Function_1.constant)(""), (n) => '"' + n + '" ');
    const statusMsg = renderStatus(tree.status);
    return `${prefix}+---${name}#${tree.fiberId.seqNumber} Status: ${statusMsg}\n`;
}
exports.renderOne = renderOne;
/**
 * @internal
 */
function renderStatus(status) {
    switch (status._tag) {
        case "Done":
            return "Done";
        case "Finishing":
            return `Finishing(${status.interrupting ? "interrupting" : ""})`;
        case "Running":
            return `Running(${status.interrupting ? "interrupting" : ""})`;
        case "Suspended": {
            const inter = status.interruptible ? "interruptible" : "uninterruptible";
            const ep = `${status.epoch} asyncs`;
            return `Suspended(${inter}, ${ep})`;
        }
    }
}
exports.renderStatus = renderStatus;
/**
 * @internal
 */
function renderHierarchy(trees) {
    return IT.reduce_(IT.map_(trees, renderOne), "", (acc, str) => acc + str);
}
exports.renderHierarchy = renderHierarchy;
function collectTraces(dumps, now) {
    return IT.map_(dumps, (d) => prettyPrint(d, now));
}
exports.collectTraces = collectTraces;
//# sourceMappingURL=fiberRenderer.js.map