local _AddonName, _EchoRaidTools = ...;


local module = _EchoRaidTools:GetModule("todo-list")
local region = GetCurrentRegion()

local constants = module.Constants

--module.
local encounterData
local encounterDataByMapId



function module.GetEventDurationOverride(eventId)
    if not eventId then return end
    return module.Constants.EventDurationOverride[eventId]
end

function module.GetRelatedEventIds(eventId)
    if not eventId then return end
    local relationIndex = module.Constants.EventCombine[eventId]
    if not relationIndex then return { [eventId] = true } end
    local ret = {}
    for id, index in pairs(module.Constants.EventCombine) do
        if index == relationIndex then
            ret[id] = true
        end
    end
    return ret
end

function module:SecondsToHumanTime(seconds)
    local days = math.floor(seconds / (24 * 60 * 60))
    seconds = seconds - (days * (24 * 60 * 60))
    local hours = math.floor(seconds / (60 * 60))
    seconds = seconds - (hours * 60 * 60)
    local minutes = math.floor(seconds / 60)
    seconds = seconds - (minutes * 60)

    if days > 0 then
        return string.format("%sd %sh", days, hours)
    elseif hours > 0 then
        return string.format("%sh %sm", hours, minutes)
    elseif minutes > 0 then
        return string.format("%sm %ss", minutes, seconds)
    else
        return string.format("%ss", seconds)
    end
end

function module.GetServerOffset()
    return module.Constants.RegionOffset[region] or 0
end

function module.GetIconForReputation(reputationID)
    --custom list of icons for reputations. should be located in things-to-maintain
    return module.Constants.ReputationIcons[reputationID]
end

function module.GetIconForQuest(questID)
    local icon = module.Constants.QuestIcons[questID]
    if icon then return icon end

    local questTypeId = C_QuestInfoSystem.GetQuestClassification(questID)
    if not questTypeId then return end
    for type, id in pairs(Enum.QuestClassification) do
        if id == questTypeId then
            return module.Constants.QuestIconByClassification[type]
        end
    end
end

local function getIconForInstance(instanceId)
    return module.Constants.InstanceIcons[instanceId]
end

function module.GetItemSlotName(itemSlotID)
    if not itemSlotID then return nil end
    local name = constants.ItemSlots[itemSlotID]
    local number = constants.ItemSlotsWithNumbers[itemSlotID]

    if number then
        name = name .. " " .. number
    end
    return name
end

local function buildEncounterData()
    local raidDifficulties = {}
    local dungeonDifficulties = {}
    for difficultyName, id in pairs(DifficultyUtil.ID) do
        local name, groupType = GetDifficultyInfo(id)
        if groupType == "raid" then
            table.insert(raidDifficulties, id)
        elseif groupType == "party" then
            table.insert(dungeonDifficulties, id)
        end
    end
    encounterData = {}
    encounterDataByMapId = {}
    for expansion = 1, module.Constants.EncounterJournalExpansions do
        EJ_SelectTier(expansion)
        for _, isRaid in ipairs({ true, false }) do
            local instanceIndex = 1
            local instanceId = EJ_GetInstanceByIndex(instanceIndex, isRaid)

            while instanceId do
                EJ_SelectInstance(instanceId);
                local instanceName, desc, bgImage, buttonImage, loreImage, buttonImage2, dungeonAreaMapID, link, shouldDisplayDifficuly, mapID =
                    EJ_GetInstanceInfo(instanceId);


                local encounterIndex = 1;
                local bossName, description, journalEncounterID, rootSectionID, journalLink, journalInstanceID, encounterID =
                    EJ_GetEncounterInfoByIndex(encounterIndex
                    , instanceId);

                local bosses = {}
                while (bossName) do
                    table.insert(bosses, {
                        index = encounterIndex,
                        name = bossName,
                        encounterId = encounterID
                    })
                    encounterIndex = encounterIndex + 1;
                    bossName, description, journalEncounterID, rootSectionID, journalLink, journalInstanceID, encounterID =
                        EJ_GetEncounterInfoByIndex(encounterIndex
                        , instanceId);
                end

                local difficultiesToCheck = isRaid and raidDifficulties or dungeonDifficulties
                local validDifficulties = {}

                for i, difficultyId in ipairs(difficultiesToCheck) do
                    if EJ_IsValidInstanceDifficulty(difficultyId) then
                        table.insert(validDifficulties, difficultyId)
                    end
                end

                encounterData[instanceId] = {
                    name = instanceName,
                    bossCount = encounterIndex - 1,
                    mapId = mapID,
                    bossInfo = bosses,
                    icon = getIconForInstance(instanceId),
                    difficulties = validDifficulties,

                }
                if mapID then
                    encounterDataByMapId[mapID] = encounterData[instanceId]
                end

                instanceIndex = instanceIndex + 1;
                instanceId = EJ_GetInstanceByIndex(instanceIndex, isRaid);
            end
        end
    end
end

function module:GetInstanceInfoByInstanceId(instanceId)
    if not instanceId then return end
    if not encounterData then
        buildEncounterData()
    end
    return encounterDataByMapId[instanceId] or encounterData[instanceId] -- todo these overlaps, fix somehow zzzzzzzzz
end

function module:GetInstances()
    if not encounterData then
        buildEncounterData()
    end
    return encounterDataByMapId
end

function module:GetFrameFromString(string)
    return _G[string] or UIParent
end

local function generateSpecList()
    local ret = {}
    local classNum = 1
    local className, classFile = GetClassInfo(classNum)
    while className do
        for specNum = 1, 4 do
            local specID, specName, _, specIcon = GetSpecializationInfoForClassID(classNum, specNum)
            if not specID then break end
            table.insert(ret, {
                className = className,
                classFile = classFile,
                specID = specID,
                specName = specName,
                specIcon = specIcon,
            })
        end
        classNum = classNum + 1
        className, classFile = GetClassInfo(classNum)
    end
    constants.specs = ret
end

generateSpecList()


local abbrevData = {
    {
        breakpoint = 10000000000000,
        significandDivisor = 1000000000000,
        abbreviation = "T",
        fractionDivisor = 1
    },
    {
        breakpoint = 1000000000000,
        significandDivisor = 100000000000,
        abbreviation = "T",
        fractionDivisor = 10
    },
    {
        breakpoint = 10000000000,
        significandDivisor = 1000000000,
        abbreviation = "B",
        fractionDivisor = 1
    },
    {
        breakpoint = 1000000000,
        significandDivisor = 100000000,
        abbreviation = "B",
        fractionDivisor = 10
    },
    {
        breakpoint = 10000000,
        significandDivisor = 1000000,
        abbreviation = "M",
        fractionDivisor = 1
    },
    {
        breakpoint = 1000000,
        significandDivisor = 100000,
        abbreviation = "M",
        fractionDivisor = 10
    },
    {
        breakpoint = 10000,
        significandDivisor = 1000,
        abbreviation = "K",
        fractionDivisor = 1
    },
    {
        breakpoint = 1000,
        significandDivisor = 100,
        abbreviation = "K",
        fractionDivisor = 10
    },
    {
        breakpoint = 100,
        significandDivisor = 0.1,
        fractionDivisor = 10
    },
    {
        breakpoint = 10,
        significandDivisor = 0.01,
        fractionDivisor = 100
    }
}

function module.AbbreviateNumbers(value)
    if not value then return "" end
    for i, data in ipairs(abbrevData) do
        if value >= data.breakpoint then
            local finalValue = math.floor(value / data.significandDivisor) / data.fractionDivisor;
            return data.abbreviation and finalValue .. data.abbreviation or tostring(finalValue);
        end
    end


    return tostring(math.floor(value / 0.001) / 1000);
end


function module.MinWithNilCheck(a, b)
    if not a then return b end
    if not b then return a end
    return min(a, b)
end
