import stringWidth from "string-width";
import cliTruncate from "cli-truncate";
import terminalSize from "terminal-size";
//#region src/utils.ts
function createWordWrapper(start, stop) {
	const mode = "soft";
	const re = mode === "hard" ? /\b/ : /(\S+\s+)/;
	return function(text) {
		return text.toString().split(re).reduce(function(acc, x) {
			if (mode === "hard") for (let i = 0; i < x.length; i += stop - start) acc.push(x.slice(i, i + stop - start));
			else acc.push(x);
			return acc;
		}, []).reduce(function(lines, rawChunk) {
			if (rawChunk === "") return lines;
			const chunk = rawChunk.replace(/\t/g, "    ");
			const i = lines.length - 1;
			if (lines[i].length + chunk.length > stop) {
				lines[i] = lines[i].replace(/\s+$/, "");
				chunk.split(/\n/).forEach(function(c) {
					lines.push(new Array(start + 1).join(" ") + c.replace(/^\s+/, ""));
				});
			} else if (chunk.match(/\n/)) {
				const xs = chunk.split(/\n/);
				lines[i] += xs.shift();
				xs.forEach(function(c) {
					lines.push(new Array(start + 1).join(" ") + c.replace(/^\s+/, ""));
				});
			} else lines[i] += chunk;
			return lines;
		}, [new Array(start + 1).join(" ")]).join("\n");
	};
}
//#endregion
//#region src/helpers.ts
/**
* Total number of columns for the terminal
*/
const TERMINAL_SIZE = terminalSize().columns;
/**
* Applies padding to the left or the right of the string by repeating
* a given char.
*
* The method is not same as `padLeft` or `padRight` from JavaScript STD lib,
* since it repeats a char regardless of the max width.
*/
function applyPadding(value, options) {
	if (options.paddingLeft) value = `${options.paddingChar.repeat(options.paddingLeft)}${value}`;
	if (options.paddingRight) value = `${value}${options.paddingChar.repeat(options.paddingRight)}`;
	return value;
}
/**
* Justify the columns to have the same width by filling
* the empty slots with a padding char.
*
* Optionally, the column can be aligned left or right.
*/
function justify(columns, options) {
	const normalizedOptions = {
		align: "left",
		paddingChar: " ",
		...options
	};
	return columns.map((column) => {
		const columnWidth = stringWidth(column);
		/**
		* Column is already same or greater than the maxWidth
		*/
		if (columnWidth >= normalizedOptions.maxWidth) return column;
		/**
		* Fill empty space on the right
		*/
		if (normalizedOptions.align === "left") return applyPadding(column, {
			paddingChar: normalizedOptions.paddingChar,
			paddingRight: normalizedOptions.maxWidth - columnWidth
		});
		/**
		* Fill empty space on the left
		*/
		return applyPadding(column, {
			paddingChar: normalizedOptions.paddingChar,
			paddingLeft: normalizedOptions.maxWidth - columnWidth
		});
	});
}
/**
* Wrap the text under the starting and the ending column.
* The first line will start at 1st column. However, from
* the 2nd line onwards, the columns before the start
* column are filled with white space.
*/
function wrap(columns, options) {
	const wrapper = createWordWrapper(options.startColumn, options.endColumn);
	if (options.trimStart) return columns.map((column) => wrapper(column).trimStart());
	return columns.map((column) => wrapper(column));
}
/**
* Truncates the text after a certain width.
*/
function truncate(columns, options) {
	return columns.map((column) => cliTruncate(column, options.maxWidth, {
		truncationCharacter: options.truncationChar || "…",
		position: options.position || "end"
	}));
}
//#endregion
export { wrap as i, justify as n, truncate as r, TERMINAL_SIZE as t };
