// SPDX-License-Identifier: Apache-2.0
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
import { inject, injectable } from 'tsyringe-neo';
import { InjectTokens } from './dependency-injection/inject-tokens.js';
import { patchInject } from './dependency-injection/container-helper.js';
let HelpRenderer = class HelpRenderer {
    logger;
    constructor(logger) {
        this.logger = logger;
        this.logger = patchInject(logger, InjectTokens.SoloLogger, this.constructor.name);
    }
    splitAtClosestWhitespace(input, maxLength = 120) {
        if (input.length <= maxLength) {
            return [input, ''];
        }
        const splitIndex = input.lastIndexOf(' ', maxLength);
        if (splitIndex === -1) {
            return [input, ''];
        }
        return [input.slice(0, Math.max(0, splitIndex)), input.slice(Math.max(0, splitIndex + 1))];
    }
    createFlagsTable(lines) {
        const table = [];
        for (const line of lines) {
            let columns = line.split(/(--[1-9a-zA-Z|-]+)/);
            // if the description contains --flag there will be more than the expected amount of columns
            // joins all columns after columns[2]
            if (columns.length > 3) {
                const firstPart = columns.slice(0, 2);
                const secondPart = columns.slice(2).join(' ');
                columns = [...firstPart, secondPart];
            }
            const descriptions = columns[2].split(/(\[.+])/);
            columns[2] = descriptions[0];
            columns[3] = descriptions[1] || '';
            columns = columns.map((column) => column.trim());
            table.push(columns);
        }
        return table;
    }
    sortFlagsTable(table) {
        table.sort((row1, row2) => {
            return row1[1].localeCompare(row2[1]);
        });
        const requiredTable = table.filter((row) => row[3].includes('required'));
        const optionalTable = table.filter((row) => !row[3].includes('required'));
        return requiredTable.concat(optionalTable);
    }
    calculateMaxColumnLengths(table) {
        const columnMaxLengths = [0, 0, 0, 0];
        for (const row of table) {
            for (const [index, element] of row.entries()) {
                columnMaxLengths[index] = Math.max(columnMaxLengths[index], element.length);
            }
        }
        return columnMaxLengths;
    }
    wrapFlagsTable(table, columnMaxLengths, wrap) {
        const wrappedTable = [];
        for (const row of table) {
            if (row[2].length > wrap) {
                const description = row[2];
                let splitDescription = this.splitAtClosestWhitespace(description, wrap);
                wrappedTable.push([row[0], row[1], splitDescription[0], row[3]]);
                while (splitDescription[1] && splitDescription[1].length > 0) {
                    splitDescription = this.splitAtClosestWhitespace(splitDescription[1], wrap);
                    wrappedTable.push(['', '', splitDescription[0], '']);
                }
            }
            else {
                wrappedTable.push(row);
            }
        }
        return wrappedTable;
    }
    getDescriptionWrap(terminalWidth, columnMaxLengths) {
        let wrap = terminalWidth - columnMaxLengths[0] - columnMaxLengths[1] - columnMaxLengths[3] - 6;
        if (wrap < 30) {
            wrap = 30;
        } // set min and max values
        if (wrap > 70) {
            wrap = 70;
        }
        if (columnMaxLengths[2] < wrap) {
            wrap = columnMaxLengths[2];
        }
        else {
            columnMaxLengths[2] = wrap;
        }
        return wrap;
    }
    addColumnPadding(table, columnMaxLengths) {
        const outputLines = [];
        for (const row of table) {
            const line = [];
            for (const [index, element] of row.entries()) {
                line.push(element.padEnd(columnMaxLengths[index]));
            }
            outputLines.push(line.join('  '));
        }
        return outputLines;
    }
    render(rootCmd, rawHelp) {
        const splittingString = 'Options:\n';
        const splitOutput = rawHelp.split(splittingString);
        if (splitOutput.length < 2) {
            this.logger.showUser(rawHelp);
            return;
        }
        let finalOutput = splitOutput[0] + splittingString;
        let lines = splitOutput[1].split('\n');
        lines = lines.map((line) => line.replace(/^\s+/, ''));
        // Formatting for flag options
        const table = this.createFlagsTable(lines);
        // apply sorting
        const sortedTable = this.sortFlagsTable(table);
        const columnMaxLengths = this.calculateMaxColumnLengths(sortedTable);
        // wrap the description column at the wrapping point
        const terminalWidth = rootCmd.terminalWidth();
        const wrap = this.getDescriptionWrap(terminalWidth, columnMaxLengths);
        const wrappedTable = this.wrapFlagsTable(sortedTable, columnMaxLengths, wrap);
        const outputLines = this.addColumnPadding(wrappedTable, columnMaxLengths);
        finalOutput += '\n';
        finalOutput += outputLines.join('\n');
        finalOutput += '\n';
        this.logger.showUser(finalOutput);
    }
};
HelpRenderer = __decorate([
    injectable(),
    __param(0, inject(InjectTokens.SoloLogger)),
    __metadata("design:paramtypes", [Object])
], HelpRenderer);
export { HelpRenderer };
//# sourceMappingURL=help-renderer.js.map