function CzechQuestsAddon:GetData(key, id)
    if CzechQuestsAddon.data[key] then
        if key == "quest" then
            if CzechQuestsAddon.data[key][id] then
                local quest = CzechQuestsAddon.data[key][id];

                local function ResolveFemaleVersion(maleVersion, femaleVersion)
                    local gender = UnitSex("player")
                    if gender == 2 then
                        return maleVersion
                    else
                        return femaleVersion == "" and maleVersion or femaleVersion
                    end
                end

                local standardQuest = {
                    title = ResolveFemaleVersion(quest.titleMale, quest.titleFemale),
                    objective = ResolveFemaleVersion(quest.objectiveMale, quest.objectiveFemale),
                    description = ResolveFemaleVersion(quest.descriptionMale, quest.descriptionFemale),
                    progress = ResolveFemaleVersion(quest.progressMale, quest.progressFemale),
                    completion = ResolveFemaleVersion(quest.completionMale, quest.completionFemale),
                }
                return standardQuest
            end
        elseif CzechQuestsAddon.data[key][id] then
            return CzechQuestsAddon.data[key][id]
        end
    end
    return nil
end

function CzechQuestsAddon:replacePlaceholders(text)
    if text == nil then
        return text
    end

    local playerName = UnitName("player")
    local _, playerClass = UnitClass("player")
    local _, playerRace = UnitRace("player")

    local class = CzechQuestsAddon:GetData("class", playerClass);
    local race = CzechQuestsAddon:GetData("race", playerRace);

    local formatted = text;
    formatted = string.gsub(formatted, '<name>', playerName);

    formatted = string.gsub(formatted, '<cF0>', class.f0);
    formatted = string.gsub(formatted, '<cF1>', class.f1);
    formatted = string.gsub(formatted, '<cF2>', class.f2);
    formatted = string.gsub(formatted, '<cF3>', class.f3);
    formatted = string.gsub(formatted, '<cF4>', class.f4);
    formatted = string.gsub(formatted, '<cF5>', class.f5);

    formatted = string.gsub(formatted, '<cM0>', class.m0);
    formatted = string.gsub(formatted, '<cM1>', class.m1);
    formatted = string.gsub(formatted, '<cM2>', class.m2);
    formatted = string.gsub(formatted, '<cM3>', class.m3);
    formatted = string.gsub(formatted, '<cM4>', class.m4);

    formatted = string.gsub(formatted, '<cP0>', class.p0);
    formatted = string.gsub(formatted, '<cP1>', class.p1);
    formatted = string.gsub(formatted, '<cP3>', class.m3);

    formatted = string.gsub(formatted, '<rF0>', race.f0);
    formatted = string.gsub(formatted, '<rF1>', race.f1);
    formatted = string.gsub(formatted, '<rF2>', race.f2);
    formatted = string.gsub(formatted, '<rF3>', race.f3);
    formatted = string.gsub(formatted, '<rF4>', race.f4);
    formatted = string.gsub(formatted, '<rF5>', race.f5);

    formatted = string.gsub(formatted, '<rM0>', race.m0);
    formatted = string.gsub(formatted, '<rM1>', race.m1);
    formatted = string.gsub(formatted, '<rM2>', race.m2);
    formatted = string.gsub(formatted, '<rM3>', race.m3);
    formatted = string.gsub(formatted, '<rM4>', race.m4);

    formatted = string.gsub(formatted, '<rP0>', race.p0);
    formatted = string.gsub(formatted, '<rP1>', race.p1);
    formatted = string.gsub(formatted, '<rP3>', race.p3);

    return formatted
end

function CzechQuestsAddon:dumpTable(tbl, indent)
    -- Initialize indent if not provided
    indent = indent or 0

    -- Check if the input is actually a table
    if type(tbl) ~= "table" then
        print(string.rep("  ", indent) .. tostring(tbl))
        return
    end

    -- Iterate through the table and print keys and values
    for k, v in pairs(tbl) do
        local formatting = string.rep("  ", indent) .. tostring(k) .. ": "
        if type(v) == "table" then
            print(formatting)
            CzechQuestsAddon:dumpTable(v, indent + 1)
        elseif type(v) == "boolean" then
            print(formatting .. (v and "true" or "false"))
        else
            print(formatting .. tostring(v))
        end
    end
end