local P = {}

---List generator
---@generic T
---@param count integer
---@param generator fun(i: integer): T
---@return T[]
function P.generateList(count, generator)
    if count <= 0 then return {} end

    local xs = {}
    for i = 0, count - 1, 1 do
        xs[i] = generator(i)
    end

    return xs
end

--- Returns the sign of a number
--- @param number number
--- @return -1 | 0 | 1
function P.sign(number)
    return (number > 0 and 1) or (number == 0 and 0) or -1
end

--- Applies a side effect for each value of a table
--- @generic T
--- @param table {[any] : T}
--- @param fn fun(el: T): nil
function P.each(table, fn)
    for _, value in pairs(table) do
        fn(value)
    end
end

--- Returns true if the given function returns true for all the values in the given table.
--- Returns false after the first value which evaluates to false.
--- @generic T
--- @param table {[any] : T}
--- @param fn fun(el: T): boolean
function P.all(table, fn)
    for _, value in ipairs(table) do
        if not fn(value) then return false end
    end
    return true
end

--- Returns true if the given function returns true for any of the values in the given table.
--- @generic T
--- @param table {[any] : T}
--- @param fn fun(el: T): boolean
function P.any(table, fn)
    for _, value in ipairs(table) do
        if fn(value) then return true end
    end
    return false
end

--- Returns the list of keys of the given table.
--- The order of the keys is not guaranteed.
--- @generic T
--- @param t {T: any}
--- @return T[]
function P.keys(t)
    local _t = {}
    for k, _ in pairs(t) do
        table.insert(_t, k)
    end
    return _t
end

--- Linear interpolation
function P.lerp(from, to, t)
    return from + (to - from) * t
end

--- Compares two tables by their fields
--- @param t1 table
--- @param t2 table
--- @return boolean
function P.deepComparison(t1, t2)
    for k, v in pairs(t1) do
        if type(v) == "table" and type(t2[k]) == "table" then
            if not P.deepComparison(v, t2[k]) then return false end
        elseif t2[k] ~= v then
            return false
        end
    end
    return true
end

return P
