local UI = nil
function showBosstiary()
    UI = g_ui.loadUI("bosstiary", contentContainer)
    UI:show()
    Cyclopedia.Bosstiary.Page = 1
    g_game.requestBosstiaryInfo()
    UI.FilterBase.BaneIcon:setTooltip(
        "Bane\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 5\nExpertise: 15\nMastery: 30")
    -- UI.FilterBase.BaneIcon:setTooltipAlign(AlignTopLeft)
    UI.FilterBase.ArchfoeIcon:setTooltip(
        "Archfoe\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 10\nExpertise: 30\nMastery: 60")
    -- UI.FilterBase.ArchfoeIcon:setTooltipAlign(AlignTopLeft)
    UI.FilterBase.NemesisIcon:setTooltip(
        "Nemesis\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 10\nExpertise: 30\nMastery: 60")
    -- UI.FilterBase.NemesisIcon:setTooltipAlign(AlignTopLeft)
    UI.StarBase.Info1:setTooltip("Once you have reached the Prowess level, you can assign the boss\nto a boss slot.")
    -- UI.StarBase.Info1:setTooltipAlign(AlignTopLeft)
    UI.StarBase.Info2:setTooltip(
        "Once you have reached the Expertise Level, you can display the\nboss on a Podium of Vigour.")
    -- UI.StarBase.Info2:setTooltipAlign(AlignTopLeft)
    UI.StarBase.Info3:setTooltip(
        "Once you have reached the Mastery Level, youl will receive an\nadditional 25% loot bonus when the boss is assigned to a boss slot.")
    -- UI.StarBase.Info3:setTooltipAlign(AlignTopLeft)
    controllerCyclopedia.ui.CharmsBase:setVisible(false)
    controllerCyclopedia.ui.GoldBase:setVisible(false)
    controllerCyclopedia.ui.BestiaryTrackerButton:setVisible(false)
    if g_game.getClientVersion() >= 1410 then
        controllerCyclopedia.ui.CharmsBase1410:setVisible(false)
    end
end

Cyclopedia.Bosstiary = {}

local CATEGORY = {
    BANE = 0,
    NEMESIS = 2,
    ARCHFOE = 1
}
local CONFIG = {
    [0] = {
        EXPERTISE = 100,
        PROWESS = 25,
        MASTERY = 300
    },
    {
        EXPERTISE = 20,
        PROWESS = 5,
        MASTERY = 60
    },
    {
        EXPERTISE = 3,
        PROWESS = 1,
        MASTERY = 5
    }
}

local BOSSTIARY_TRACKER_OVERRIDE_TTL = 5000

local function getBosstiaryTrackerOverrides()
    Cyclopedia.BosstiaryTrackerOverrides = Cyclopedia.BosstiaryTrackerOverrides or {}
    return Cyclopedia.BosstiaryTrackerOverrides
end

local function getBosstiaryTrackerOverride(raceId)
    local overrides = getBosstiaryTrackerOverrides()
    local override = overrides[raceId]

    if override and override.expiresAt <= g_clock.millis() then
        overrides[raceId] = nil
        return nil
    end

    return override
end

local function setBosstiaryTrackerOverride(raceId, checked)
    local overrides = getBosstiaryTrackerOverrides()
    overrides[raceId] = {
        checked = checked,
        expiresAt = g_clock.millis() + BOSSTIARY_TRACKER_OVERRIDE_TTL
    }

    scheduleEvent(function()
        local override = overrides[raceId]
        if override and override.expiresAt <= g_clock.millis() then
            overrides[raceId] = nil
        end
    end, BOSSTIARY_TRACKER_OVERRIDE_TTL + 250)
end

local function getEffectiveBosstiaryTrackerState(raceId, serverState, confirmServerState)
    local trackerState = serverState == 1 and 1 or 0
    local override = getBosstiaryTrackerOverride(raceId)

    if not override then
        return trackerState
    end

    local desiredState = override.checked and 1 or 0
    if confirmServerState and trackerState == desiredState then
        getBosstiaryTrackerOverrides()[raceId] = nil
        return trackerState
    end

    return desiredState
end

local function setBosstiaryTrackCheck(widget, checked)
    local originalCallback = widget.onCheckChange
    widget.onCheckChange = nil
    widget:setChecked(checked)
    widget.onCheckChange = originalCallback
    widget.bosstiaryTrackerState = checked
end

local function updateBosstiaryTrackerState(raceId, checked)
    if not Cyclopedia.Bosstiary then
        return
    end

    local trackerState = checked and 1 or 0

    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures or {}) do
        for _, creature in ipairs(creatures) do
            if creature.raceId == raceId then
                creature.isTrackerActived = trackerState
            end
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures or {}) do
        if creature.raceId == raceId then
            creature.isTrackerActived = trackerState
        end
    end
end

local function addBosstiaryTrackerEntry(trackerData, data, confirmServerState)
    local config = CONFIG[data.category]
    local trackerState = getEffectiveBosstiaryTrackerState(data.raceId, data.isTrackerActived, confirmServerState)

    if not config or trackerState ~= 1 or data.kills < 1 then
        return
    end

    table.insert(trackerData, {
        data.raceId,
        data.kills,
        config.PROWESS,
        config.EXPERTISE,
        config.MASTERY,
        1
    })
end

local function findBosstiaryTrackerEntry(raceId)
    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures or {}) do
        for _, creature in ipairs(creatures) do
            if creature.raceId == raceId then
                local trackerData = {}
                addBosstiaryTrackerEntry(trackerData, creature, false)
                return trackerData[1]
            end
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures or {}) do
        if creature.raceId == raceId then
            local trackerData = {}
            addBosstiaryTrackerEntry(trackerData, creature, false)
            return trackerData[1]
        end
    end

    for _, entry in ipairs(Cyclopedia.storedBosstiaryTrackerData or {}) do
        if entry[1] == raceId then
            local copy = {unpack(entry)}
            copy[6] = 1
            return copy
        end
    end
end

function Cyclopedia.mergeBosstiaryTrackerOverrides(data)
    local overrides = getBosstiaryTrackerOverrides()
    local mergedData = {}
    local seenRaceIds = {}
    local sourceData = data or {}

    if #sourceData == 0 and next(overrides) and Cyclopedia.storedBosstiaryTrackerData and
        #Cyclopedia.storedBosstiaryTrackerData > 0 then
        sourceData = Cyclopedia.storedBosstiaryTrackerData
    end

    for _, entry in ipairs(sourceData) do
        local raceId = entry[1]
        local trackerState = getEffectiveBosstiaryTrackerState(raceId, 1, true)

        seenRaceIds[raceId] = true

        if trackerState == 1 then
            local copy = {unpack(entry)}
            copy[6] = 1
            table.insert(mergedData, copy)
        end
    end

    for raceId, override in pairs(overrides) do
        if not seenRaceIds[raceId] and not getBosstiaryTrackerOverride(raceId) then
            override = nil
        end

        if override and override.checked and not seenRaceIds[raceId] then
            local entry = findBosstiaryTrackerEntry(raceId)
            if entry then
                table.insert(mergedData, entry)
            end
        end
    end

    return mergedData
end

local function copyBosstiaryTrackerEntry(entry)
    return {unpack(entry)}
end

local function setBosstiaryTrackerData(trackerData)
    Cyclopedia.BosstiaryTrackerPending = false
    Cyclopedia.storedBosstiaryTrackerData = trackerData

    if trackerMiniWindowBosstiary and Cyclopedia.onParseCyclopediaTracker then
        local previousLocalRender = Cyclopedia.BosstiaryTrackerLocalRender
        Cyclopedia.BosstiaryTrackerLocalRender = true
        Cyclopedia.onParseCyclopediaTracker(1, trackerData)
        Cyclopedia.BosstiaryTrackerLocalRender = previousLocalRender
    elseif trackerMiniWindowBosstiary and trackerMiniWindowBosstiary.contentsPanel then
        trackerMiniWindowBosstiary.contentsPanel:destroyChildren()
    end
end

local function rebuildBosstiaryTrackerDataFromCreatures()
    local trackerData = {}

    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures or {}) do
        for _, creature in ipairs(creatures) do
            addBosstiaryTrackerEntry(trackerData, creature, false)
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures or {}) do
        addBosstiaryTrackerEntry(trackerData, creature, false)
    end

    setBosstiaryTrackerData(trackerData)
end

function Cyclopedia.syncBosstiaryTrackerFromBosstiaryInfo(data)
    local trackerData = {}

    for _, dataEntry in ipairs(data or {}) do
        addBosstiaryTrackerEntry(trackerData, dataEntry, true)
    end

    setBosstiaryTrackerData(trackerData)
end

function Cyclopedia.setBosstiaryTrackerStatus(raceId, checked, sendToServer)
    raceId = tonumber(raceId)
    if not raceId then
        return
    end

    setBosstiaryTrackerOverride(raceId, checked)
    updateBosstiaryTrackerState(raceId, checked)

    if UI and UI.ListBase and UI.ListBase.BossList then
        for _, child in ipairs(UI.ListBase.BossList:getChildren()) do
            if tonumber(child:getId()) == raceId and child.TrackCheck then
                setBosstiaryTrackCheck(child.TrackCheck, checked)
            end
        end
    end

    local trackerData = {}
    for _, entry in ipairs(Cyclopedia.storedBosstiaryTrackerData or {}) do
        if entry[1] ~= raceId then
            table.insert(trackerData, copyBosstiaryTrackerEntry(entry))
        end
    end

    if checked then
        local entry = findBosstiaryTrackerEntry(raceId)
        if entry then
            table.insert(trackerData, entry)
        end
    end

    setBosstiaryTrackerData(trackerData)

    if sendToServer ~= false then
        g_game.sendStatusTrackerBestiary(raceId, checked)
    end
end

function Cyclopedia.onBosstiaryTrackCheckChange(widget)
    local raceId = tonumber(widget.raceId or widget:getParent():getId())
    if not raceId then
        return
    end

    local checked = widget:isChecked()
    if widget.bosstiaryTrackerState == checked then
        return
    end

    widget.bosstiaryTrackerState = checked
    Cyclopedia.setBosstiaryTrackerStatus(raceId, checked, true)
end

--[[ function Cyclopedia.SetBosstiaryProgress(object, value, maxValue)
    local rect = {
        height = 12,
        x = 0,
        y = 0,
        width = (maxValue < value and maxValue or value) / maxValue * 141
    }

    if value >= 0 and rect.width < 1 then
        object.fill:setVisible(false)
    else
        object.fill:setVisible(true)
    end

    object.fill:setImageRect(rect)
    object.ProgressValue:setText(value)
    object.fill:setImageSource("/game_cyclopedia/images/bestiary/fill")

end ]]

function Cyclopedia.CreateBosstiaryCreature(data)
    if not data.visible then
        return
    end

    local widget = g_ui.createWidget("BosstiaryItem", UI.ListBase.BossList)
    widget:setId(data.raceId)
    local raceData = g_things.getRaceData(data.raceId)
    local icons = {
        [CATEGORY.BANE] = "/game_cyclopedia/images/boss/icon_bane",
        [CATEGORY.ARCHFOE] = "/game_cyclopedia/images/boss/icon_archfoe",
        [CATEGORY.NEMESIS] = "/game_cyclopedia/images/boss/icon_nemesis"
    }

    local function format(string)
        if #string > 19 then
            return string:sub(1, 16) .. "..."
        else
            return string
        end
    end

    local fullText = ""

    if data.kills >= CONFIG[data.category].MASTERY then
        fullText = "(fully unlocked)"
    end

    widget.ProgressBorder1:setTooltip(string.format(" %d / %d %s", data.kills, CONFIG[data.category].PROWESS, fullText))
    widget.ProgressBorder2:setTooltip(
        string.format(" %d / %d %s", data.kills, CONFIG[data.category].EXPERTISE, fullText))
    widget.ProgressBorder3:setTooltip(string.format(" %d / %d %s", data.kills, CONFIG[data.category].MASTERY, fullText))

    if data.kills >= CONFIG[data.category].PROWESS then
        widget.bronzeStar:setImageSource("/game_cyclopedia/images/boss/icon_star_bronze")
    else
        widget.silverStar:setImageSource("/game_cyclopedia/images/boss/icon_star_dark")
    end

    if data.kills >= CONFIG[data.category].EXPERTISE then
        widget.silverStar:setImageSource("/game_cyclopedia/images/boss/icon_star_silver")
    else
        widget.silverStar:setImageSource("/game_cyclopedia/images/boss/icon_star_dark")
    end

    if data.kills >= CONFIG[data.category].MASTERY then
        widget.goldStar:setImageSource("/game_cyclopedia/images/boss/icon_star_gold")
    else
        widget.goldStar:setImageSource("/game_cyclopedia/images/boss/icon_star_dark")
    end

    widget.TypeIcon:setImageSource(icons[data.category])

    if data.category == CATEGORY.BANE then
        widget.TypeIcon:setTooltip(
            "Bane\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 5\nExpertise: 15\nMastery: 30")
        -- widget.TypeIcon:setTooltipAlign(AlignTopLeft)
    elseif data.category == CATEGORY.ARCHFOE then
        widget.TypeIcon:setTooltip(
            "Archfoe\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 10\nExpertise: 30\nMastery: 60")
        -- widget.TypeIcon:setTooltipAlign(AlignTopLeft)
    elseif data.category == CATEGORY.NEMESIS then
        widget.TypeIcon:setTooltip(
            "Nemesis\n\nFor unlocking a level, you will receive the following boss points:\nProwess: 10\nExpertise: 30\nMastery: 60")
        -- widget.TypeIcon:setTooltipAlign(AlignTopLeft)
    end
    widget.ProgressValue:setText(data.kills)

    Cyclopedia.SetBestiaryProgress(46,widget.ProgressBack, widget.ProgressBack33, widget.ProgressBack55,  data.kills, CONFIG[data.category].PROWESS, CONFIG[data.category].EXPERTISE, CONFIG[data.category].MASTERY)

    widget.Sprite:setOutfit(raceData.outfit)
    widget.Sprite:getCreature():setStaticWalking(1000)
    if data.unlocked then
        widget.Sprite:getCreature():setShader("")
        widget:setText(format(data.name))
        if g_game.getClientVersion() >= 1320 then
            widget.TrackCheck:enable()
            widget.TrackCheck.raceId = data.raceId
            setBosstiaryTrackCheck(widget.TrackCheck, data.isTrackerActived == 1)
        else
            widget.TrackCheck:hide()
        end
    else
        widget.Sprite:getCreature():setShader("Outfit - cyclopedia-black")
        widget.TrackCheck:disable()

    end
end

function Cyclopedia.LoadBosstiaryCreatures(data)
    Cyclopedia.syncBosstiaryTrackerFromBosstiaryInfo(data)

    if not UI or not UI.PageValue then
        return
    end
    local maxCategoriesPerPage = 8

    Cyclopedia.Bosstiary.Creatures = {}
    Cyclopedia.Bosstiary.NotVisibleCreatures = {}
    Cyclopedia.Bosstiary.Page = Cyclopedia.Bosstiary.Page or 1
    Cyclopedia.Bosstiary.TotalPages = math.ceil(#data / maxCategoriesPerPage)

    if Cyclopedia.Bosstiary.TotalPages < 1 then
        Cyclopedia.Bosstiary.TotalPages = 1
    end

    if Cyclopedia.Bosstiary.Page > Cyclopedia.Bosstiary.TotalPages then
        Cyclopedia.Bosstiary.Page = Cyclopedia.Bosstiary.TotalPages
    end

    UI.PageValue:setText(string.format("%d / %d", Cyclopedia.Bosstiary.Page, Cyclopedia.Bosstiary.TotalPages))

    local page = 1

    Cyclopedia.Bosstiary.Creatures[page] = {}

    local validCreatures = {}

    for i, dataEntry in ipairs(data) do
        local raceData = g_things.getRaceData(dataEntry.raceId)
        local creature = {
            visible = true,
            raceId = dataEntry.raceId,
            name = raceData and raceData.name or "?",
            kills = dataEntry.kills,
            category = dataEntry.category,
            isTrackerActived = getEffectiveBosstiaryTrackerState(dataEntry.raceId, dataEntry.isTrackerActived, true),
            unlocked = dataEntry.kills > 0 and true or false
        }

        table.insert(validCreatures, creature)
    end

    table.sort(validCreatures, function(a, b)
        if a.name == "?" and b.name ~= "?" then
            return false
        elseif a.name ~= "?" and b.name == "?" then
            return true
        elseif a.unlocked and not b.unlocked then
            return true
        elseif not a.unlocked and b.unlocked then
            return false
        else
            return a.name < b.name
        end
    end)

    for i = 1, #validCreatures do
        local creature = validCreatures[i]

        if creature.visible then
            table.insert(Cyclopedia.Bosstiary.Creatures[page], creature)
        else
            table.insert(Cyclopedia.Bosstiary.NotVisibleCreatures[page], creature)
        end

        if i % maxCategoriesPerPage == 0 and i < #validCreatures then
            page = page + 1
            Cyclopedia.Bosstiary.Creatures[page] = {}
        end
    end

    if Cyclopedia.pendingBosstiaryRaceId and Cyclopedia.focusBosstiaryRace and
        Cyclopedia.focusBosstiaryRace(Cyclopedia.pendingBosstiaryRaceId) then
        Cyclopedia.pendingBosstiaryRaceId = nil
        return
    end

    Cyclopedia.LoadBosstiaryCreature(Cyclopedia.Bosstiary.Page)
    Cyclopedia.verifyBosstiaryButtons()
end

function Cyclopedia.LoadBosstiaryCreature(page)
    if not Cyclopedia.Bosstiary.Creatures[page] then
        return
    end

    UI.ListBase.BossList:destroyChildren()

    for _, data in ipairs(Cyclopedia.Bosstiary.Creatures[page]) do
        Cyclopedia.CreateBosstiaryCreature(data)
    end
end

function Cyclopedia.focusBosstiaryRace(raceId)
    raceId = tonumber(raceId)
    if not raceId or not Cyclopedia.Bosstiary or not Cyclopedia.Bosstiary.Creatures then
        return false
    end

    for page, creatures in ipairs(Cyclopedia.Bosstiary.Creatures) do
        for _, creature in ipairs(creatures) do
            if creature.raceId == raceId then
                Cyclopedia.Bosstiary.Page = page
                Cyclopedia.LoadBosstiaryCreature(page)
                Cyclopedia.verifyBosstiaryButtons()
                return true
            end
        end
    end

    return false
end

function Cyclopedia.verifyBosstiaryButtons()
    if not UI or not UI.PageValue then
        return
    end
    local page = Cyclopedia.Bosstiary.Page
    local totalPages = Cyclopedia.Bosstiary.TotalPages

    local function updateButtonState(button, condition)
        if condition then
            button:enable()
        else
            button:disable()
        end
    end

    local function updatePageValue(currentPage, maxPages)
        UI.PageValue:setText(string.format("%d / %d", currentPage, maxPages))
    end

    updateButtonState(UI.PrevPageButton, page > 1)
    updateButtonState(UI.NextPageButton, page < totalPages)
    updatePageValue(page, totalPages)
end

function Cyclopedia.changeBosstiaryPage(prev, next)
    if next then
        Cyclopedia.Bosstiary.Page = Cyclopedia.Bosstiary.Page + 1
    end

    if prev then
        Cyclopedia.Bosstiary.Page = Cyclopedia.Bosstiary.Page - 1
    end

    Cyclopedia.LoadBosstiaryCreature(Cyclopedia.Bosstiary.Page)
    Cyclopedia.verifyBosstiaryButtons()
end

function Cyclopedia.BosstiarySearchText(text, clear)
    local allCreatures = {}

    if clear then
        UI.SearchEdit:setText("")
    end

    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures) do
        for _, creature in ipairs(creatures) do
            table.insert(allCreatures, creature)
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures) do
        table.insert(allCreatures, creature)
    end

    if text ~= "" then
        for _, creature in ipairs(allCreatures) do
            if not creature.unlocked then
                creature.visible = false
            elseif string.find(creature.name:lower(), text:lower()) == nil then
                creature.visible = false
            else
                creature.visible = true
            end
        end
    else
        for _, creature in ipairs(allCreatures) do
            creature.visible = true
        end
    end

    Cyclopedia.ReadjustPages()
end

function Cyclopedia.changeBosstiaryFilter(widget, isCheck)
    widget:setChecked(not isCheck)

    local id = widget:getId()
    local allCreatures = {}

    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures) do
        for _, creature in ipairs(creatures) do
            table.insert(allCreatures, creature)
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures) do
        table.insert(allCreatures, creature)
    end

    for _, creature in ipairs(allCreatures) do
        if id == "BaneCheck" then
            if creature.category == CATEGORY.BANE then
                creature.visible = widget:isChecked()
            end
        elseif id == "ArchfoeCheck" then
            if creature.category == CATEGORY.ARCHFOE then
                creature.visible = widget:isChecked()
            end
        elseif id == "NemesisCheck" then
            if creature.category == CATEGORY.NEMESIS then
                creature.visible = widget:isChecked()
            end
        elseif id == "NoKillsCheck" then
            if creature.kills < 1 then
                creature.visible = widget:isChecked()
            end
        elseif id == "FewKillsCheck" then
            if creature.kills ~= 0 and creature.kills < CONFIG[creature.category].PROWESS then
                creature.visible = widget:isChecked()
            end
        elseif id == "ProwessCheck" then
            if creature.kills ~= 0 and creature.kills >= CONFIG[creature.category].PROWESS and creature.kills <=
                CONFIG[creature.category].EXPERTISE then
                creature.visible = widget:isChecked()
            end
        elseif id == "ExpertiseCheck" then
            if creature.kills ~= 0 and creature.kills >= CONFIG[creature.category].EXPERTISE and creature.kills <=
                CONFIG[creature.category].MASTERY then
                creature.visible = widget:isChecked()
            end
        elseif id == "MasteryCheck" and creature.kills ~= 0 and creature.kills >= CONFIG[creature.category].MASTERY then
            creature.visible = widget:isChecked()
        end
    end

    Cyclopedia.ReadjustPages()
end

function Cyclopedia.ReadjustPages()
    local maxCategoriesPerPage = 8
    local allCreatures = {}

    for _, creatures in ipairs(Cyclopedia.Bosstiary.Creatures) do
        for _, creature in ipairs(creatures) do
            table.insert(allCreatures, creature)
        end
    end

    for _, creature in ipairs(Cyclopedia.Bosstiary.NotVisibleCreatures) do
        table.insert(allCreatures, creature)
    end

    table.sort(allCreatures, function(a, b)
        if a.name == "?" and b.name ~= "?" then
            return false
        elseif a.name ~= "?" and b.name == "?" then
            return true
        elseif a.unlocked and not b.unlocked then
            return true
        elseif not a.unlocked and b.unlocked then
            return false
        else
            return a.name < b.name
        end
    end)

    Cyclopedia.Bosstiary.Creatures = {}
    Cyclopedia.Bosstiary.NotVisibleCreatures = {}

    local page = 1

    Cyclopedia.Bosstiary.Creatures[page] = {}

    for i, creature in ipairs(allCreatures) do
        if creature.visible then
            table.insert(Cyclopedia.Bosstiary.Creatures[page], creature)

            if #Cyclopedia.Bosstiary.Creatures[page] == maxCategoriesPerPage then
                page = page + 1
                Cyclopedia.Bosstiary.Creatures[page] = {}
            end
        else
            table.insert(Cyclopedia.Bosstiary.NotVisibleCreatures, creature)
        end
    end

    local totalVisible = 0

    for _, pageCreatures in ipairs(Cyclopedia.Bosstiary.Creatures) do
        totalVisible = totalVisible + #pageCreatures
    end

    Cyclopedia.Bosstiary.TotalPages = math.ceil(totalVisible / maxCategoriesPerPage)

    if Cyclopedia.Bosstiary.Page > Cyclopedia.Bosstiary.TotalPages then
        Cyclopedia.Bosstiary.Page = 1
    end

    if not UI or not UI.PageValue then
        return
    end
    UI.PageValue:setText(string.format("%d / %d", Cyclopedia.Bosstiary.Page, Cyclopedia.Bosstiary.TotalPages))
    Cyclopedia.LoadBosstiaryCreature(Cyclopedia.Bosstiary.Page)
    Cyclopedia.verifyBosstiaryButtons()
end
