"use strict";
/*
 * @poppinss/utils
 *
 * (c) Harminder Virk <virk@adonisjs.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
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;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateRandom = exports.toMs = exports.toBytes = exports.ordinalize = exports.isEmpty = exports.prettyMs = exports.prettyBytes = exports.toSentence = exports.encodeSymbols = exports.escapeHTML = exports.condenseWhitespace = exports.excerpt = exports.truncate = exports.singularize = exports.pluralize = exports.noCase = exports.dotCase = exports.sentenceCase = exports.capitalCase = exports.pascalCase = exports.dashCase = exports.snakeCase = exports.camelCase = exports.defineUncountableRule = exports.defineIrregularRule = exports.titleCase = exports.toSlug = void 0;
const ms_1 = __importDefault(require("ms"));
const truncatise_1 = __importDefault(require("truncatise"));
const crypto_1 = require("crypto");
const he_1 = __importDefault(require("he"));
const changeCase = __importStar(require("change-case"));
const bytes_1 = __importDefault(require("bytes"));
const pluralize_1 = require("pluralize");
var slugify_1 = require("slugify");
Object.defineProperty(exports, "toSlug", { enumerable: true, get: function () { return __importDefault(slugify_1).default; } });
const SMALL_WORDS = /\b(?:an?d?|a[st]|because|but|by|en|for|i[fn]|neither|nor|o[fnr]|only|over|per|so|some|tha[tn]|the|to|up|upon|vs?\.?|versus|via|when|with|without|yet)\b/i;
const TOKENS = /[^\s:–—-]+|./g;
const WHITESPACE = /\s/;
const IS_MANUAL_CASE = /.(?=[A-Z]|\..)/;
const ALPHANUMERIC_PATTERN = /[A-Za-z0-9\u00C0-\u00FF]/;
/**
 * The method is a copy/paste from the "title-case" package. They have
 * a dependency on "tslib", which I don't want.
 */
function titleCase(input) {
    let output = '';
    let result;
    while ((result = TOKENS.exec(input)) !== null) {
        const { 0: token, index } = result;
        if (!IS_MANUAL_CASE.test(token) &&
            (!SMALL_WORDS.test(token) || index === 0 || index + token.length === input.length) &&
            (input.charAt(index + token.length) !== ':' ||
                WHITESPACE.test(input.charAt(index + token.length + 1)))) {
            output += token.replace(ALPHANUMERIC_PATTERN, (char) => char.toUpperCase());
            continue;
        }
        output += token;
    }
    return output;
}
exports.titleCase = titleCase;
/**
 * Normalizes base64 string by removing special chars and padding
 */
function normalizeBase64(value) {
    return value.replace(/\+/g, '-').replace(/\//g, '_').replace(/\=/g, '');
}
/**
 * Define an irregular rule
 */
function defineIrregularRule(singleValue, pluralValue) {
    (0, pluralize_1.addIrregularRule)(singleValue, pluralValue);
}
exports.defineIrregularRule = defineIrregularRule;
/**
 * Define uncountable rule
 */
function defineUncountableRule(word) {
    (0, pluralize_1.addUncountableRule)(word);
}
exports.defineUncountableRule = defineUncountableRule;
/**
 * Convert string to camelcase
 */
function camelCase(value) {
    return changeCase.camelCase(value);
}
exports.camelCase = camelCase;
/**
 * Convert string to snakecase
 */
function snakeCase(value) {
    return changeCase.snakeCase(value);
}
exports.snakeCase = snakeCase;
/**
 * Convert string to dashcase
 */
function dashCase(value, options) {
    if (options && options.capitalize) {
        return changeCase.headerCase(value);
    }
    return changeCase.paramCase(value);
}
exports.dashCase = dashCase;
/**
 * Convert string to pascal case
 */
function pascalCase(value) {
    return changeCase.pascalCase(value);
}
exports.pascalCase = pascalCase;
/**
 * Convert string to capital case
 */
function capitalCase(value) {
    return changeCase.capitalCase(value);
}
exports.capitalCase = capitalCase;
/**
 * Convert string to sentence case
 */
function sentenceCase(value) {
    return changeCase.sentenceCase(value);
}
exports.sentenceCase = sentenceCase;
/**
 * Convert string to dot case
 */
function dotCase(value) {
    return changeCase.dotCase(value);
}
exports.dotCase = dotCase;
/**
 * Remove all sort of casing from the string
 */
function noCase(value) {
    return changeCase.noCase(value);
}
exports.noCase = noCase;
/**
 * Pluralize a word
 */
function pluralize(word) {
    return (0, pluralize_1.plural)(word);
}
exports.pluralize = pluralize;
/**
 * Singularize a word
 */
function singularize(word) {
    return (0, pluralize_1.singular)(word);
}
exports.singularize = singularize;
/**
 * Truncate a sentence till a give limit of characters
 */
function truncate(sentence, charactersLimit, options) {
    return (0, truncatise_1.default)(sentence, {
        TruncateLength: charactersLimit,
        /**
         * Do not complete words when "completeWords" is not explicitly set
         * to true
         */
        Strict: options && options.completeWords === true ? false : true,
        StripHTML: false,
        TruncateBy: 'characters',
        Suffix: options && options.suffix,
    });
}
exports.truncate = truncate;
/**
 * Same as truncate, but strips out the HTML
 */
function excerpt(sentence, charactersLimit, options) {
    return (0, truncatise_1.default)(sentence, {
        TruncateLength: charactersLimit,
        /**
         * Do not complete words when "completeWords" is not explicitly set
         * to true
         */
        Strict: options && options.completeWords === true ? false : true,
        StripHTML: true,
        TruncateBy: 'characters',
        Suffix: options && options.suffix,
    });
}
exports.excerpt = excerpt;
/**
 * Condenses multiple whitespaces from a string
 */
function condenseWhitespace(value) {
    return value.trim().replace(/\s{2,}/g, ' ');
}
exports.condenseWhitespace = condenseWhitespace;
/**
 * Escape HTML entities
 */
function escapeHTML(value, options) {
    value = he_1.default.escape(value);
    if (options && options.encodeSymbols) {
        value = encodeSymbols(value, { allowUnsafeSymbols: true });
    }
    return value;
}
exports.escapeHTML = escapeHTML;
/**
 * Encode symbols that aren’t printable ASCII symbols
 */
function encodeSymbols(value, options) {
    return he_1.default.encode(value, options);
}
exports.encodeSymbols = encodeSymbols;
/**
 * Convert array of values to a sentence
 */
function toSentence(values, options) {
    /**
     * Empty array
     */
    if (values.length === 0) {
        return '';
    }
    /**
     * Just one item
     */
    if (values.length === 1) {
        return values[0];
    }
    /**
     * Giving some love to two items, so that one can use oxford comma's
     */
    if (values.length === 2) {
        return `${values[0]}${options?.pairSeparator || ' and '}${values[1]}`;
    }
    const normalized = Object.assign({ separator: ', ', lastSeparator: ', and ' }, options);
    /**
     * Make sentence
     */
    return `${values.slice(0, -1).join(normalized.separator)}${normalized.lastSeparator}${values[values.length - 1]}`;
}
exports.toSentence = toSentence;
/**
 * Convert a number to a human readable string
 */
function prettyBytes(value, options) {
    return bytes_1.default.format(value, options);
}
exports.prettyBytes = prettyBytes;
/**
 * Convert milliseconds to a human readable string
 */
function prettyMs(value, options) {
    return (0, ms_1.default)(value, options);
}
exports.prettyMs = prettyMs;
/**
 * Find if a string is empty. Including any number of whitespaces
 */
function isEmpty(value) {
    return value.trim().length === 0;
}
exports.isEmpty = isEmpty;
/**
 * Ordinalize a give number or string
 */
function ordinalize(value) {
    const transformedValue = Math.abs(typeof value === 'string' ? parseInt(value) : value);
    if (!Number.isFinite(transformedValue) || Number.isNaN(transformedValue)) {
        throw new Error('Cannot ordinalize NAN or infinite numbers');
    }
    const percent = transformedValue % 100;
    if (percent >= 10 && percent <= 20) {
        return `${value}th`;
    }
    const decimal = transformedValue % 10;
    switch (decimal) {
        case 1:
            return `${value}st`;
        case 2:
            return `${value}nd`;
        case 3:
            return `${value}rd`;
        default:
            return `${value}th`;
    }
}
exports.ordinalize = ordinalize;
/**
 * Converts unit expression to bytes
 */
function toBytes(value) {
    if (typeof value === 'number') {
        return value;
    }
    return bytes_1.default.parse(value);
}
exports.toBytes = toBytes;
/**
 * Converts time expression to milliseconds
 */
function toMs(value) {
    if (typeof value === 'number') {
        return value;
    }
    return (0, ms_1.default)(value);
}
exports.toMs = toMs;
/**
 * Generates a random string for a given size
 */
function generateRandom(size) {
    const bits = (size + 1) * 6;
    const buffer = (0, crypto_1.randomBytes)(Math.ceil(bits / 8));
    return normalizeBase64(buffer.toString('base64')).slice(0, size);
}
exports.generateRandom = generateRandom;
