"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.uncapitalizeFirstLetter = exports.trimSuffix = exports.trimPrefix = exports.removeSubstring = exports.removeNonAlphanumericCharacters = exports.removeCharactersBefore = exports.removeAllCharacters = exports.parseSemanticVersion = exports.getPartialMatch = exports.getObjectPartialMatch = exports.getMapPartialMatch = exports.capitalizeFirstLetter = void 0;
const types_1 = require("./types");
const utils_1 = require("./utils");
function capitalizeFirstLetter(string) {
    if (string === "") {
        return string;
    }
    const firstCharacter = string.charAt(0);
    const capitalizedFirstLetter = firstCharacter.toUpperCase();
    const restOfString = string.slice(1);
    return `${capitalizedFirstLetter}${restOfString}`;
}
exports.capitalizeFirstLetter = capitalizeFirstLetter;
/**
 * Helper function to get the closest key from a map based on partial search text. (It only searches
 * through the keys, not the values.)
 *
 * Note that:
 * - Spaces are automatically removed from the search text.
 * - Both the search text and the strings to search through are converted to lowercase before
 *   attempting to find a match.
 *
 * For example:
 *
 * ```ts
 * const map = new <string, number>Map([
 *   ["foo", 123],
 *   ["bar", 456],
 * ]);
 * const searchText = "f";
 * const match = getMapPartialMatch(map, searchText); // match is now equal to ["foo", 123]
 * ```
 *
 * @returns If a match was found, returns a tuple of the map key and value. If a match was not
 *          found, returns undefined.
 */
function getMapPartialMatch(searchText, map) {
    const keys = [...map.keys()];
    const matchingKey = getPartialMatch(searchText, keys);
    if (matchingKey === undefined) {
        return undefined;
    }
    const value = map.get(matchingKey);
    (0, utils_1.assertDefined)(value, `Failed to get the map value corresponding to the partial match of: ${matchingKey}`);
    return [matchingKey, value];
}
exports.getMapPartialMatch = getMapPartialMatch;
/**
 * Helper function to get the closest key from an object based on partial search text. (It only
 * searches through the keys, not the values.)
 *
 * Note that:
 * - Spaces are automatically removed from the search text.
 * - Both the search text and the strings to search through are converted to lowercase before
 *   attempting to find a match.
 *
 * For example:
 *
 * ```ts
 * const object = {
 *   foo: 123,
 *   bar: 456,
 * };
 * const searchText = "f";
 * const match = getObjectPartialMatch(object, searchText); // match is now equal to ["foo", 123]
 * ```
 *
 * @returns If a match was found, returns a tuple of the map key and value. If a match was not
 *          found, returns undefined.
 */
function getObjectPartialMatch(searchText, object) {
    const keys = Object.keys(object);
    const matchingKey = getPartialMatch(searchText, keys);
    if (matchingKey === undefined) {
        return undefined;
    }
    const value = object[matchingKey];
    (0, utils_1.assertDefined)(value, `Failed to get the object value corresponding to the partial match of: ${matchingKey}`);
    return [matchingKey, value];
}
exports.getObjectPartialMatch = getObjectPartialMatch;
/**
 * Helper function to get the closest value from an array of strings based on partial search text.
 *
 * Note that:
 * - Spaces are automatically removed from the search text.
 * - Both the search text and the strings to search through are converted to lowercase before
 *   attempting to find a match.
 *
 * For example:
 *
 * ```ts
 * const array = ["foo", "bar"];
 * const searchText = "f";
 * const match = getPartialMatch(array, searchText); // match is now equal to "foo"
 *
 * @returns If a match was found, returns the array element. If a match was not
 * found, returns undefined.
 * ```
 */
function getPartialMatch(searchText, array) {
    const sortedArray = array.toSorted();
    searchText = searchText.toLowerCase();
    searchText = searchText.replaceAll(" ", "");
    const matchingElements = sortedArray.filter((element) => element.toLowerCase().startsWith(searchText));
    matchingElements.sort();
    return matchingElements[0];
}
exports.getPartialMatch = getPartialMatch;
/**
 * Helper function to parse a Semantic Versioning string into its individual constituents. Returns
 * undefined if the submitted string was not a proper Semantic Version string.
 *
 * https://semver.org/
 */
function parseSemanticVersion(versionString) {
    const [majorVersionString, minorVersionString, patchVersionString] = string.match(versionString, "(%d+).(%d+).(%d+)");
    if (majorVersionString === undefined ||
        minorVersionString === undefined ||
        patchVersionString === undefined) {
        return undefined;
    }
    const majorVersion = (0, types_1.parseIntSafe)(majorVersionString);
    const minorVersion = (0, types_1.parseIntSafe)(minorVersionString);
    const patchVersion = (0, types_1.parseIntSafe)(patchVersionString);
    if (majorVersion === undefined ||
        minorVersion === undefined ||
        patchVersion === undefined) {
        return undefined;
    }
    return { majorVersion, minorVersion, patchVersion };
}
exports.parseSemanticVersion = parseSemanticVersion;
function removeAllCharacters(string, character) {
    return string.replaceAll(character, "");
}
exports.removeAllCharacters = removeAllCharacters;
/**
 * Helper function to remove all of the characters in a string before a given substring. Returns the
 * modified string.
 */
function removeCharactersBefore(string, substring) {
    const index = string.indexOf(substring);
    return string.slice(index);
}
exports.removeCharactersBefore = removeCharactersBefore;
/** Helper function to remove all characters from a string that are not letters or numbers. */
function removeNonAlphanumericCharacters(str) {
    const [returnValue, _] = string.gsub(str, "%W", "");
    return returnValue;
}
exports.removeNonAlphanumericCharacters = removeNonAlphanumericCharacters;
/**
 * Helper function to remove one or more substrings from a string, if they exist. Returns the
 * modified string.
 *
 * This function is variadic, meaning that you can pass as many substrings as you want to remove.
 */
function removeSubstring(string, ...substrings) {
    for (const substring of substrings) {
        string = string.replaceAll(substring, "");
    }
    return string;
}
exports.removeSubstring = removeSubstring;
/** Helper function to trim a prefix from a string, if it exists. Returns the trimmed string. */
function trimPrefix(string, prefix) {
    if (!string.startsWith(prefix)) {
        return string;
    }
    return string.slice(prefix.length);
}
exports.trimPrefix = trimPrefix;
/** Helper function to trim a suffix from a string, if it exists. Returns the trimmed string. */
function trimSuffix(string, prefix) {
    if (!string.endsWith(prefix)) {
        return string;
    }
    const endCharacter = string.length - prefix.length;
    return string.slice(0, endCharacter);
}
exports.trimSuffix = trimSuffix;
function uncapitalizeFirstLetter(string) {
    if (string === "") {
        return string;
    }
    const firstCharacter = string.charAt(0);
    const uncapitalizedFirstLetter = firstCharacter.toLowerCase();
    const restOfString = string.slice(1);
    return `${uncapitalizedFirstLetter}${restOfString}`;
}
exports.uncapitalizeFirstLetter = uncapitalizeFirstLetter;
