local _, PUP = ...

PUP.otherChecker = {}

-- Element variables
local nameFrameWidth = 150
local versionFramePaddingLeft = 10
local versionFramePaddingRight = 40
local elementHeight = 32

-- Version tables for GUIDs, used for comparison against their new table
-- Updates are only done if something changed
local cachedVersionsTables = {}

local scrollFrame, scrollBar, dataProvider, scrollView, labelFrame
local labels = {} -- Label fontstrings
local labelTitles = {
    "MRT-Notiz",
    "Ignorierliste",
    "RCLC",
    "Manaforge Vandals"
}

PUP.highestSeenRCLCVersion = "0.0.0"
local mrtNoteHash

-- Compares two RCLC TOC versions
-- Returns -1 if version1 is higher, 0 if they are equal, 1 if version2 is higher
function PUP:CompareRCLCVersions(version1, version2)
    local major1, minor1, patch1 = version1:match("(%d+).(%d+).(%d+)")
    local major2, minor2, patch2 = version2:match("(%d+).(%d+).(%d+)")

    if major1 ~= major2 then
        major1 = tonumber(major1)
        major2 = tonumber(major2)

        return major1 > major2 and -1 or 1
    elseif minor1 ~= minor2 then
        minor1 = tonumber(minor1)
        minor2 = tonumber(minor2)

        return minor1 > minor2 and -1 or 1
    elseif patch1 ~= patch2 then
        patch1 = tonumber(patch1)
        patch2 = tonumber(patch2)

        return patch1 > patch2 and -1 or 1
    else
        return 0
    end
end

-- Checks a unit's new version table against their known one
-- Returns true if something changed
local function ShouldUpdate(GUID, newVersionsTable)
    local oldVersionsTable = cachedVersionsTables[GUID]

    if not oldVersionsTable then return true end
    if not newVersionsTable then return false end

    return not tCompare(oldVersionsTable, newVersionsTable, 3)
end

local function PositionLabels(_, width)
    local firstVersionFrameX = nameFrameWidth + versionFramePaddingLeft
    local versionFramesTotalWidth = width - firstVersionFrameX - versionFramePaddingRight - elementHeight
    local versionFrameSpacing = versionFramesTotalWidth / (#labels - 1)

    for i, versionFrame in ipairs(labels) do
        versionFrame:SetPoint("BOTTOM", labelFrame, "BOTTOMLEFT", firstVersionFrameX + (i - 1) * versionFrameSpacing + 0.5 * elementHeight, 0)
    end
end

local function BuildLabels()
    if not labelFrame then
        labelFrame = CreateFrame("Frame", nil, PUP.otherCheckWindow)
        labelFrame:SetPoint("BOTTOMLEFT", scrollFrame, "TOPLEFT", 0, 4)
        labelFrame:SetPoint("BOTTOMRIGHT", scrollFrame, "TOPRIGHT", 0, 4)
        labelFrame:SetHeight(24)

        labelFrame:SetScript("OnSizeChanged", PositionLabels)
    end

    for i, displayName in ipairs(labelTitles) do
        if not labels[i] then
            labels[i] = labelFrame:CreateFontString(nil, "OVERLAY")

            labels[i]:SetFontObject(PUFont15)
        end

        labels[i]:SetText(string.format("|cff%s%s|r", PUP.gs.visual.colorStrings.white, displayName))
    end

    PositionLabels(nil, scrollFrame:GetWidth())
end

function PUP.otherChecker:UpdateCheckElementForUnit(unit, versionsTable, force)
    local GUID = UnitGUID(unit)

    if not GUID then return end
    if not (force or ShouldUpdate(GUID, versionsTable)) then return end

    -- If this is the player's version table, and the mrt note hash is different, rebuild all elements (not just the player's)
    if UnitIsUnit(unit, "player") and versionsTable and versionsTable.mrtNoteHash and (not mrtNoteHash or mrtNoteHash ~= versionsTable.mrtNoteHash) then
        mrtNoteHash = versionsTable.mrtNoteHash
        PUP.otherChecker:RebuildAllCheckElements()

        return
    end

    cachedVersionsTables[GUID] = CopyTable(versionsTable or {})

    -- If this unit already has an element, remove it
    dataProvider:RemoveByPredicate(
        function(elementData)
            return elementData.GUID == GUID
        end
    )

    -- Create new data
    local _, class, _, _, _, name = GetPlayerInfoByGUID(GUID)

    if not (class and name) then return end

    local colorStr = RAID_CLASS_COLORS[class].colorStr
    local coloredName = string.format("|c%s%s|r", colorStr, name)

    local data = {
        GUID = GUID,
        unit = GetUnitName(unit, true),
        name = name, -- Used for sorting
        coloredName = coloredName
    }

    if versionsTable then
        data.auraUpdater = true -- Whether AuraUpdater is active
        data.mrtNoteHash = versionsTable.mrtNoteHash
        data.ignores = versionsTable.ignores
        data.RCLC = versionsTable.RCLC
		data.raidRenown = versionsTable.raidRenown
        data.maxRenownPossible = versionsTable.maxRenownPossible
        data.questsUnlocked = versionsTable.questsUnlocked
        data.completedQuests = versionsTable.completedQuests
    end
	
    dataProvider:Insert(data)
end

function PUP.otherChecker:AddCheckElementsForNewUnits()
    for unit in PUP:IterateGroupMembers() do
        local GUID = UnitGUID(unit)

        if not PUP:GetVersionsTableForGUID(GUID) then
            PUP.otherChecker:UpdateCheckElementForUnit(unit)
        end
    end
end

-- Iterates existing elements, and removes those whose units are no longer in our group
function PUP.otherChecker:RemoveCheckElementsForInvalidUnits()
    for i, data in dataProvider:ReverseEnumerate() do
        local unit = data.unit

        if not UnitExists(unit) then
            PUP:UpdateVersionsTableForGUID(data.GUID, nil)
            cachedVersionsTables[data.GUID] = nil

            dataProvider:RemoveIndex(i)
        end
    end
end

function PUP.otherChecker:RebuildAllCheckElements()
    for unit in PUP:IterateGroupMembers() do
        local GUID = UnitGUID(unit)
        local versionsTable = PUP:GetVersionsTableForGUID(GUID)

        PUP.otherChecker:UpdateCheckElementForUnit(unit, versionsTable, true)
    end

    BuildLabels()
end

local function CheckElementInitializer(frame, data)
    local versionFrameCount = #labelTitles

    -- Create version frames
    if not frame.versionFrames then frame.versionFrames = {} end

    for i = 1, versionFrameCount do
        local subFrame = frame.versionFrames[i] or CreateFrame("Frame", nil, frame)

        if not subFrame.versionsBehindIcon then
            subFrame.versionsBehindIcon = CreateFrame("Frame", nil, subFrame)
            subFrame.versionsBehindIcon:SetSize(24, 24)
            subFrame.versionsBehindIcon:SetPoint("CENTER", subFrame, "CENTER")

            subFrame.versionsBehindIcon.tex = subFrame.versionsBehindIcon:CreateTexture(nil, "BACKGROUND")
            subFrame.versionsBehindIcon.tex:SetAllPoints()
        end

        subFrame:SetSize(elementHeight, elementHeight)

        frame.versionFrames[i] = subFrame
    end

    if not frame.coloredName then
        frame.coloredName = frame:CreateFontString(nil, "OVERLAY")

        frame.coloredName:SetFontObject(PUFont21)
        frame.coloredName:SetPoint("LEFT", frame, "LEFT", 8, 0)
    end

    frame.coloredName:SetText(string.format("|cff%s%s|r", PUP.gs.visual.colorStrings.white, data.coloredName))

    -- MRT Note
    local versionFrame = frame.versionFrames[1]

    if not data.mrtNoteHash then
        if data.auraUpdater then
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen über die MRT-Notiz erhalten.|n|nDer Benutzer verwendet eine veraltete Version des Prepull Updaters oder hat MRT deaktiviert."
            )
        else
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen über die MRT-Notiz erhalten.|n|nDer Benutzer hat den Prepull Updater nicht an."
            )
        end
    elseif mrtNoteHash == data.mrtNoteHash then
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-checkmark")

        PUP:AddTooltip(
            versionFrame,
            "Die MRT-Notiz ist die gleiche wie deine."
        )
    else
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-redx")

        PUP:AddTooltip(
            versionFrame,
            "Die MRT-Notiz unterscheidet sich von deiner."
        )
    end

    -- Ignore list
    versionFrame = frame.versionFrames[2]

    if not data.ignores then
        if data.auraUpdater then
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen über ignorierte Spieler empfangen.|n|nBenutzer führt eine veraltete Version des Prepull Updater aus."
            )
        else
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen über ignorierte Spieler empfangen.|n|nBenutzer führt den Prepull Updater nicht aus."
            )
        end
    elseif next(data.ignores) then
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-redx")

        local ignoredPlayers = ""

        for _, ignoredPlayer in ipairs(data.ignores) do
            ignoredPlayers = string.format("%s|n%s", ignoredPlayers, PUP:ClassColorName(ignoredPlayer))
        end

        PUP:AddTooltip(
            versionFrame,
            string.format("Spieler auf der Ignorierliste:%s", ignoredPlayers)
        )
    else
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-checkmark")

        PUP:AddTooltip(
            versionFrame,
            "Keine Gruppenmitglieder auf der Ignorierliste."
        )
    end

    -- RCLC
    versionFrame = frame.versionFrames[3]

    if data.oldVersion then
        versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

        PUP:AddTooltip(
            versionFrame,
            "Keine Informationen zur RCLC-Version empfangen.|n|nBenutzer führt eine veraltete Version des Prepull Updater aus."
        )
    elseif not data.RCLC then
        if data.auraUpdater then
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen zu RCLC empfangen.|n|nBenutzer führt eine veraltete Version des Prepull Updater aus oder hat RCLC deaktiviert."
            )
        else
            versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")

            PUP:AddTooltip(
                versionFrame,
                "Keine Informationen zur RCLC-Notiz empfangen.|n|nBenutzer führt den Prepull Updater nicht aus."
            )
        end
    elseif PUP:CompareRCLCVersions(PUP.highestSeenRCLCVersion, data.RCLC) == -1 then
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-redx")

        PUP:AddTooltip(
            versionFrame,
            string.format("Benutzer hat eine veraltete RCLC-Version.|n|nNeueste Version: %s|n%s's Version: %s", PUP.highestSeenRCLCVersion, data.coloredName, data.RCLC)
        )
    else
        versionFrame.versionsBehindIcon.tex:SetAtlas("common-icon-checkmark")

        PUP:AddTooltip(
            versionFrame,
            "Die RCLC-Version ist auf dem neuesten Stand."
        )
    end

    versionFrame = frame.versionFrames[4]

    local renownLevel = data.raidRenown
    local numUnlocked = data.questsUnlocked
    local maxRenownPossible = data.maxRenownPossible
    local completedCount = data.completedQuests

    if renownLevel == nil then
        -- Falls kein Renown-Wert verfügbar ist, zeige alternativ ein Icon und einen Tooltip
        versionFrame.versionsBehindIcon.tex:SetAtlas("QuestTurnin")
        PUP:AddTooltip(
            versionFrame,
            "Keine Informationen über den Ruflevel erhalten.|n" ..
            "Benutzer führt entweder den Prepull Updater nicht aus oder es liegt ein Fehler vor."
        )
        -- Entferne ggf. vorhandenen Text, damit nichts angezeigt wird:
        if versionFrame.renownText then
            versionFrame.renownText:SetText("")
        end
    else
        -- Renown-Wert vorhanden: Zeige den Wert als Text statt als Icon
        if not versionFrame.renownText then
            versionFrame.renownText = versionFrame:CreateFontString(nil, "OVERLAY")
            versionFrame.renownText:SetFontObject(PUFont15)  -- Passe das FontObject an deine UI an
            versionFrame.renownText:SetPoint("CENTER", versionFrame, "CENTER")
        end

        local colorLevel = "FFFFD700"
        local colorBonus = "FFFFD700"

        if (renownLevel < maxRenownPossible) then
            colorLevel = "FFFF0F0F"
        end

        if (completedCount < numUnlocked) then
            colorBonus = "FFFF0F0F"
        end

        local currentBonus = completedCount*3
        local maxBonus = numUnlocked*3

        versionFrame.renownText:SetText(string.format("|c%s%d|r |c%s(+%d%%)|r", colorLevel, renownLevel, colorBonus,
        currentBonus))
		
		versionFrame.versionsBehindIcon.tex:SetTexture(nil)
		
        -- Auch hier kannst du einen Tooltip hinzufügen, der den Wert näher erklärt.
        PUP:AddTooltip(
            versionFrame,
            string.format("Aktueller Ruflevel: %d/%d \nAktueller Bonus: +%d/%d%%", renownLevel, maxRenownPossible,
                currentBonus, maxBonus)
        )
    end

    if not frame.PositionVersionFrames then
        function frame.PositionVersionFrames(_, width)
            local firstVersionFrameX = nameFrameWidth + versionFramePaddingLeft
            local versionFramesTotalWidth = width - firstVersionFrameX - versionFramePaddingRight - elementHeight
            local versionFrameSpacing = versionFramesTotalWidth / (#labelTitles - 1)

            for i, vFrame in ipairs(frame.versionFrames) do
                vFrame:SetPoint("LEFT", frame, "LEFT", firstVersionFrameX + (i - 1) * versionFrameSpacing, 0)
            end
        end
    end

    frame.PositionVersionFrames(nil, frame:GetWidth())

    frame:SetScript("OnSizechanged", frame.PositionVersionFrames)
end

function PUP:InitializeOtherChecker()
    scrollFrame = CreateFrame("Frame", nil, PUP.otherCheckWindow, "WowScrollBoxList")
    scrollFrame:SetPoint("TOPLEFT", PUP.otherCheckWindow, "TOPLEFT", 4, -32)
    scrollFrame:SetPoint("BOTTOMRIGHT", PUP.otherCheckWindow, "BOTTOMRIGHT", -24, 4)

    scrollBar = CreateFrame("EventFrame", nil, PUP.otherCheckWindow, "MinimalScrollBar")
    scrollBar:SetPoint("TOP", scrollFrame, "TOPRIGHT", 12, 0)
    scrollBar:SetPoint("BOTTOM", scrollFrame, "BOTTOMRIGHT", 12, 16)

    dataProvider = CreateDataProvider()
    scrollView = CreateScrollBoxListLinearView()

    scrollView:SetElementExtent(elementHeight)
    scrollView:SetElementInitializer("Frame", CheckElementInitializer)
    scrollView:SetDataProvider(dataProvider)

    ScrollUtil.InitScrollBoxListWithScrollBar(scrollFrame, scrollBar, scrollView)


    dataProvider:SetSortComparator(
        function(data1, data2)
            local noteOK1 = data1.mrtNoteHash and data1.mrtNoteHash == mrtNoteHash
            local noteOK2 = data2.mrtNoteHash and data2.mrtNoteHash == mrtNoteHash

            local ignoresOK1 = data1.ignores and not next(data1.ignores)
            local ignoresOK2 = data2.ignores and not next(data2.ignores)

            local rclcOK1 = data1.RCLC and data1.RCLC == PUP.highestSeenRCLCVersion
            local rclcOK2 = data2.RCLC and data2.RCLC == PUP.highestSeenRCLCVersion

            if noteOK1 ~= noteOK2 then
                return noteOK2
            elseif ignoresOK1 ~= ignoresOK2 then
                return ignoresOK2
            elseif rclcOK1 ~= rclcOK2 then
                return rclcOK2
            else
                return data1.name < data2.name
            end
        end
    )

    -- Border
    local borderColor = PUP.gs.visual.borderColor
    PUP:AddBorder(scrollFrame)
    scrollFrame:SetBorderColor(borderColor.r, borderColor.g, borderColor.b)

    PUP.otherChecker:RebuildAllCheckElements()
end