local ____lualib = require("lualib_bundle")
local __TS__Spread = ____lualib.__TS__Spread
local __TS__ObjectKeys = ____lualib.__TS__ObjectKeys
local __TS__ArrayToSorted = ____lualib.__TS__ArrayToSorted
local __TS__StringReplaceAll = ____lualib.__TS__StringReplaceAll
local __TS__StringStartsWith = ____lualib.__TS__StringStartsWith
local __TS__ArrayFilter = ____lualib.__TS__ArrayFilter
local __TS__ArraySort = ____lualib.__TS__ArraySort
local __TS__StringSlice = ____lualib.__TS__StringSlice
local __TS__StringEndsWith = ____lualib.__TS__StringEndsWith
local ____exports = {}
local ____types = require("functions.types")
local parseIntSafe = ____types.parseIntSafe
local ____utils = require("functions.utils")
local assertDefined = ____utils.assertDefined
--- 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 ____exports.getPartialMatch(self, searchText, array)
    local sortedArray = __TS__ArrayToSorted(array)
    searchText = string.lower(searchText)
    searchText = __TS__StringReplaceAll(searchText, " ", "")
    local matchingElements = __TS__ArrayFilter(
        sortedArray,
        function(____, element) return __TS__StringStartsWith(
            string.lower(element),
            searchText
        ) end
    )
    __TS__ArraySort(matchingElements)
    return matchingElements[1]
end
function ____exports.capitalizeFirstLetter(self, ____string)
    if ____string == "" then
        return ____string
    end
    local firstCharacter = string.sub(____string, 1, 1)
    local capitalizedFirstLetter = string.upper(firstCharacter)
    local restOfString = string.sub(____string, 2)
    return capitalizedFirstLetter .. restOfString
end
--- 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 ____exports.getMapPartialMatch(self, searchText, map)
    local keys = {__TS__Spread(map:keys())}
    local matchingKey = ____exports.getPartialMatch(nil, searchText, keys)
    if matchingKey == nil then
        return nil
    end
    local value = map:get(matchingKey)
    assertDefined(nil, value, "Failed to get the map value corresponding to the partial match of: " .. matchingKey)
    return {matchingKey, value}
end
--- 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 ____exports.getObjectPartialMatch(self, searchText, object)
    local keys = __TS__ObjectKeys(object)
    local matchingKey = ____exports.getPartialMatch(nil, searchText, keys)
    if matchingKey == nil then
        return nil
    end
    local value = object[matchingKey]
    assertDefined(nil, value, "Failed to get the object value corresponding to the partial match of: " .. matchingKey)
    return {matchingKey, value}
end
--- 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.
-- 
-- @see https ://semver.org/
function ____exports.parseSemanticVersion(self, versionString)
    local majorVersionString, minorVersionString, patchVersionString = string.match(versionString, "(%d+).(%d+).(%d+)")
    if majorVersionString == nil or minorVersionString == nil or patchVersionString == nil then
        return nil
    end
    local majorVersion = parseIntSafe(nil, majorVersionString)
    local minorVersion = parseIntSafe(nil, minorVersionString)
    local patchVersion = parseIntSafe(nil, patchVersionString)
    if majorVersion == nil or minorVersion == nil or patchVersion == nil then
        return nil
    end
    return {majorVersion = majorVersion, minorVersion = minorVersion, patchVersion = patchVersion}
end
function ____exports.removeAllCharacters(self, ____string, character)
    return __TS__StringReplaceAll(____string, character, "")
end
--- Helper function to remove all of the characters in a string before a given substring. Returns the
-- modified string.
function ____exports.removeCharactersBefore(self, ____string, substring)
    local index = (string.find(____string, substring, nil, true) or 0) - 1
    return __TS__StringSlice(____string, index)
end
--- Helper function to remove all characters from a string that are not letters or numbers.
function ____exports.removeNonAlphanumericCharacters(self, str)
    local returnValue, _ = string.gsub(str, "%W", "")
    return returnValue
end
--- 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 ____exports.removeSubstring(self, ____string, ...)
    local substrings = {...}
    for ____, substring in ipairs(substrings) do
        ____string = __TS__StringReplaceAll(____string, substring, "")
    end
    return ____string
end
--- Helper function to trim a prefix from a string, if it exists. Returns the trimmed string.
function ____exports.trimPrefix(self, ____string, prefix)
    if not __TS__StringStartsWith(____string, prefix) then
        return ____string
    end
    return __TS__StringSlice(____string, #prefix)
end
--- Helper function to trim a suffix from a string, if it exists. Returns the trimmed string.
function ____exports.trimSuffix(self, ____string, prefix)
    if not __TS__StringEndsWith(____string, prefix) then
        return ____string
    end
    local endCharacter = #____string - #prefix
    return __TS__StringSlice(____string, 0, endCharacter)
end
function ____exports.uncapitalizeFirstLetter(self, ____string)
    if ____string == "" then
        return ____string
    end
    local firstCharacter = string.sub(____string, 1, 1)
    local uncapitalizedFirstLetter = string.lower(firstCharacter)
    local restOfString = string.sub(____string, 2)
    return uncapitalizedFirstLetter .. restOfString
end
return ____exports
