---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)
---@class WTAPI
local WTAPI = WTAPI

local LibDeflate = LibStub:GetLibrary("LibDeflate")
local LibSerialize = LibStub:GetLibrary("LibSerialize")
local LDBIcon = LibStub("LibDBIcon-1.0")

-- Main window
local MIN_WINDOW_WIDTH = 700
local MIN_WINDOW_HEIGHT = 400

local WTUI = Private.WildThingsUI
local BACKGROUND_COLOR = WTUI.settings.WIDGET_BACKGROUND_COLOR
local BACKGROUND_COLOR_ACTIVE = WTUI.settings.WIDGET_ACTIVE_BACKGROUND_COLOR

local mandatoryWAsButton, optionalWAsButton, auraCheckButton, otherCheckButton
local mandatoryWAsList, optionalWAsList, auraCheckGrid, otherCheckGrid


local function ResizeHeaderButtons(_, buttonFrameWidth)
    local combinedButtonWidth = buttonFrameWidth - 16

    mandatoryWAsButton:SetWidth(combinedButtonWidth / 4)
    optionalWAsButton:SetWidth(combinedButtonWidth / 4)
    auraCheckButton:SetWidth(combinedButtonWidth / 4)
    otherCheckButton:SetWidth(combinedButtonWidth / 4)
end


-- Called when the installed version of an aura supplied by WildThings changes for the player
function Private:OnPlayerAuraUpdate()
    mandatoryWAsList:Rebuild()
    optionalWAsList:Rebuild()
end

-- Called whenever the versions table for a group member changes (including our own)
function Private:OnVersionsTableUpdate(unit, versionsTable)
    auraCheckGrid:UpdateVersionsTableForUnit(unit, versionsTable)
    otherCheckGrid:UpdateVersionsTableForUnit(unit, versionsTable)
end

-- When the MRT hash changes for the player, we want to fully rebuild the other check grid
-- The reason for this, is that the MRT cell for every row is compared to ours
function Private:OnMRTHashUpdate()
    otherCheckGrid:UpdateVersionsTableForUnit("player", Private:GetPlayerVersionsTable())

    otherCheckGrid:FullRebuild()
end

-- Called when we receive a highest addon/weakaura version than those we had previously seen
-- We want to fully rebuild the checker grids, since this change has to be reflected in every row
function Private:OnHighestSeenVersionsUpdate()
    mandatoryWAsList:Rebuild()
    optionalWAsList:Rebuild()
    auraCheckGrid:FullRebuild()
    otherCheckGrid:FullRebuild()
end

-- Updates the minimum resize bounds for the AuraUpdater window, based on the min width of the check grids
-- This is called whenever the titles for a check grid header change
function Private:UpdateWindowResizeBounds()
    local auraCheckGridWidth = auraCheckGrid and auraCheckGrid:GetMinimumWidth() or 0
    local otherCheckGridWidth = otherCheckGrid and otherCheckGrid:GetMinimumWidth() or 0

    local minWidth = math.max(MIN_WINDOW_WIDTH, auraCheckGridWidth, otherCheckGridWidth)
    local minHeight = MIN_WINDOW_HEIGHT

    Private.window:SetResizeBounds(minWidth, minHeight)

    -- If the size of the window is currently smaller than the minimum size, increase it
    local currentWidth, currentHeight = Private.window:GetSize()

    Private.window:SetSize(
        math.max(currentWidth, minWidth),
        math.max(currentHeight, minHeight)
    )
end

function Private:InitializeInterfaceUpdate()
    -- Window
    Private.window = Private:CreateWindow(nil, true, true, true)

    Private.window:RaiseOnClick()
    Private.window:SetFrameStrata("HIGH")
    Private.window:SetPoint("CENTER")
    Private.window:SetShown(false)

    Private.window:AddButton(
        "Interface\\Addons\\WildThings\\Media\\Textures\\Cogwheel.tga",
        "Settings",
        function()
            Private.settingsWindow:SetShown(not Private.settingsWindow:IsShown())
        end
    )

    -- Wild Things Logo
    if not Private.window.logoFrame then
        Private.window.logoFrame = CreateFrame("Frame", nil, Private.window)
        Private.window.logoFrame:SetPoint("TOPLEFT", Private.window, 3, -3)
        --Private.window.logoFrame:SetHeight(MOVER_FRAME_HEIGHT)
        Private.window.logoFrame:SetSize(16, 16)
        Private.window.logoFrame.Texture = Private.window.logoFrame:CreateTexture()
        Private.window.logoFrame.Texture:SetSnapToPixelGrid(false)
        Private.window.logoFrame.Texture:SetTexelSnappingBias(0)
        Private.window.logoFrame.Texture:SetTexture(string.format("Interface\\Addons\\%s\\Media\\Icons\\icon.tga", AddonName))
        Private.window.logoFrame.Texture:SetAllPoints(Private.window.logoFrame)
    end

    -- Button frame
    local buttonFrame = CreateFrame("Frame", nil, Private.window)

    buttonFrame:SetPoint("TOPLEFT", Private.window.moverFrame, "BOTTOMLEFT")
    buttonFrame:SetPoint("TOPRIGHT", Private.window.moverFrame, "BOTTOMRIGHT")

    buttonFrame:SetHeight(32)
    buttonFrame:SetScript("OnSizeChanged", ResizeHeaderButtons)

    -- Mandatory WAs
    mandatoryWAsButton = CreateFrame("Frame", nil, Private.window)

    mandatoryWAsButton:SetPoint("TOPLEFT", buttonFrame, "TOPLEFT", 4, -4)
    mandatoryWAsButton:SetPoint("BOTTOMLEFT", buttonFrame, "BOTTOMLEFT", 4, 0)
    mandatoryWAsButton:EnableMouse(true)

    mandatoryWAsButton.tex = mandatoryWAsButton:CreateTexture(nil, "BACKGROUND")
    mandatoryWAsButton.tex:SetAllPoints()
    mandatoryWAsButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    mandatoryWAsButton.tex:SetSnapToPixelGrid(false)
    mandatoryWAsButton.tex:SetTexelSnappingBias(0)

    mandatoryWAsButton.highlight = mandatoryWAsButton:CreateTexture(nil, "HIGHLIGHT")
    mandatoryWAsButton.highlight:SetColorTexture(1, 1, 1, 0.05)
    mandatoryWAsButton.highlight:SetAllPoints()
    mandatoryWAsButton.highlight:SetSnapToPixelGrid(false)
    mandatoryWAsButton.highlight:SetTexelSnappingBias(0)

    mandatoryWAsButton.text = mandatoryWAsButton:CreateFontString(nil, "OVERLAY")
    mandatoryWAsButton.text:SetFontObject(WildThingsFont17)
    mandatoryWAsButton.text:SetPoint("CENTER", mandatoryWAsButton, "CENTER")
    mandatoryWAsButton.text:SetText(string.format("|cff%sMandatory WAs|r", Private.gs.visual.colorStrings.white))

    mandatoryWAsButton.MakeButtonActive = function ()
        mandatoryWAsButton.tex:SetColorTexture(BACKGROUND_COLOR_ACTIVE.r, BACKGROUND_COLOR_ACTIVE.g, BACKGROUND_COLOR_ACTIVE.b, BACKGROUND_COLOR_ACTIVE.a)
    end
    mandatoryWAsButton.MakeButtonInactive = function ()
        mandatoryWAsButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    end

    mandatoryWAsButton:SetScript(
        "OnMouseDown",
        function()
            Private.mandatoryWAsWindow:Show()
            Private.optionalWAsWindow:Hide()
            Private.auraCheckWindow:Hide()
            Private.otherCheckWindow:Hide()
            mandatoryWAsButton:MakeButtonActive()
            optionalWAsButton:MakeButtonInactive()
            auraCheckButton:MakeButtonInactive()
            otherCheckButton:MakeButtonInactive()
        end
    )

    local borderColor = Private.WildThingsUI.settings.BORDER_COLOR
    Private.WildThingsUI:AddBorder(mandatoryWAsButton)
    mandatoryWAsButton:SetBorderColor(borderColor.r, borderColor.g, borderColor.b)


    -- Optional WAs
    optionalWAsButton = CreateFrame("Frame", nil, Private.window)

    optionalWAsButton:SetPoint("TOPLEFT", mandatoryWAsButton, "TOPRIGHT", 4, 0)
    optionalWAsButton:SetPoint("BOTTOMLEFT", mandatoryWAsButton, "BOTTOMRIGHT", 4, 0)
    optionalWAsButton:EnableMouse(true)

    optionalWAsButton.tex = optionalWAsButton:CreateTexture(nil, "BACKGROUND")
    optionalWAsButton.tex:SetAllPoints()
    optionalWAsButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    optionalWAsButton.tex:SetSnapToPixelGrid(false)
    optionalWAsButton.tex:SetTexelSnappingBias(0)

    optionalWAsButton.highlight = optionalWAsButton:CreateTexture(nil, "HIGHLIGHT")
    optionalWAsButton.highlight:SetColorTexture(1, 1, 1, 0.05)
    optionalWAsButton.highlight:SetAllPoints()
    optionalWAsButton.highlight:SetSnapToPixelGrid(false)
    optionalWAsButton.highlight:SetTexelSnappingBias(0)

    optionalWAsButton.text = optionalWAsButton:CreateFontString(nil, "OVERLAY")
    optionalWAsButton.text:SetFontObject(WildThingsFont17)
    optionalWAsButton.text:SetPoint("CENTER", optionalWAsButton, "CENTER")
    optionalWAsButton.text:SetText(string.format("|cff%sOptional WAs|r", Private.gs.visual.colorStrings.white))

    optionalWAsButton.MakeButtonActive = function ()
        optionalWAsButton.tex:SetColorTexture(BACKGROUND_COLOR_ACTIVE.r, BACKGROUND_COLOR_ACTIVE.g, BACKGROUND_COLOR_ACTIVE.b, BACKGROUND_COLOR_ACTIVE.a)
    end
    optionalWAsButton.MakeButtonInactive = function ()
        optionalWAsButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    end

    optionalWAsButton:SetScript(
        "OnMouseDown",
        function()
            Private.mandatoryWAsWindow:Hide()
            Private.optionalWAsWindow:Show()
            Private.auraCheckWindow:Hide()
            Private.otherCheckWindow:Hide()
            mandatoryWAsButton:MakeButtonInactive()
            optionalWAsButton:MakeButtonActive()
            auraCheckButton:MakeButtonInactive()
            otherCheckButton:MakeButtonInactive()
        end
    )

    Private.WildThingsUI:AddBorder(optionalWAsButton)
    optionalWAsButton:SetBorderColor(borderColor.r, borderColor.g, borderColor.b)


    -- Aura check button
    auraCheckButton = CreateFrame("Frame", nil, Private.window)

    auraCheckButton:SetPoint("TOPLEFT", optionalWAsButton, "TOPRIGHT", 4, 0)
    auraCheckButton:SetPoint("BOTTOMLEFT", optionalWAsButton, "BOTTOMRIGHT", 4, 0)
    auraCheckButton:EnableMouse(true)

    auraCheckButton.tex = auraCheckButton:CreateTexture(nil, "BACKGROUND")
    auraCheckButton.tex:SetAllPoints()
    auraCheckButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    auraCheckButton.tex:SetSnapToPixelGrid(false)
    auraCheckButton.tex:SetTexelSnappingBias(0)

    auraCheckButton.highlight = auraCheckButton:CreateTexture(nil, "HIGHLIGHT")
    auraCheckButton.highlight:SetColorTexture(1, 1, 1, 0.05)
    auraCheckButton.highlight:SetAllPoints()
    auraCheckButton.highlight:SetSnapToPixelGrid(false)
    auraCheckButton.highlight:SetTexelSnappingBias(0)

    auraCheckButton.text = auraCheckButton:CreateFontString(nil, "OVERLAY")
    auraCheckButton.text:SetFontObject(WildThingsFont17)
    auraCheckButton.text:SetPoint("CENTER", auraCheckButton, "CENTER")
    auraCheckButton.text:SetText(string.format("|cff%sRaid check|r", Private.gs.visual.colorStrings.white))

    auraCheckButton.MakeButtonActive = function ()
        auraCheckButton.tex:SetColorTexture(BACKGROUND_COLOR_ACTIVE.r, BACKGROUND_COLOR_ACTIVE.g, BACKGROUND_COLOR_ACTIVE.b, BACKGROUND_COLOR_ACTIVE.a)
    end
    auraCheckButton.MakeButtonInactive = function ()
        auraCheckButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    end

    auraCheckButton:SetScript(
        "OnMouseDown",
        function()
            Private.mandatoryWAsWindow:Hide()
            Private.optionalWAsWindow:Hide()
            Private.auraCheckWindow:Show()
            Private.otherCheckWindow:Hide()
            mandatoryWAsButton:MakeButtonInactive()
            optionalWAsButton:MakeButtonInactive()
            auraCheckButton:MakeButtonActive()
            otherCheckButton:MakeButtonInactive()
        end
    )

    Private.WildThingsUI:AddBorder(auraCheckButton)
    auraCheckButton:SetBorderColor(borderColor.r, borderColor.g, borderColor.b)

    -- Other check button
    otherCheckButton = CreateFrame("Frame", nil, Private.window)

    otherCheckButton:SetPoint("TOPLEFT", auraCheckButton, "TOPRIGHT", 4, 0)
    otherCheckButton:SetPoint("BOTTOMRIGHT", buttonFrame, "BOTTOMRIGHT", -4, 0)
    otherCheckButton:EnableMouse(true)

    otherCheckButton.tex = otherCheckButton:CreateTexture(nil, "BACKGROUND")
    otherCheckButton.tex:SetAllPoints()
    otherCheckButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    otherCheckButton.tex:SetSnapToPixelGrid(false)
    otherCheckButton.tex:SetTexelSnappingBias(0)

    otherCheckButton.highlight = otherCheckButton:CreateTexture(nil, "HIGHLIGHT")
    otherCheckButton.highlight:SetColorTexture(1, 1, 1, 0.05)
    otherCheckButton.highlight:SetAllPoints()
    otherCheckButton.highlight:SetSnapToPixelGrid(false)
    otherCheckButton.highlight:SetTexelSnappingBias(0)

    otherCheckButton.text = otherCheckButton:CreateFontString(nil, "OVERLAY")
    otherCheckButton.text:SetFontObject(WildThingsFont17)
    otherCheckButton.text:SetPoint("CENTER", otherCheckButton, "CENTER")
    otherCheckButton.text:SetText(string.format("|cff%sOther check|r", Private.gs.visual.colorStrings.white))

    otherCheckButton.MakeButtonActive = function ()
        otherCheckButton.tex:SetColorTexture(BACKGROUND_COLOR_ACTIVE.r, BACKGROUND_COLOR_ACTIVE.g, BACKGROUND_COLOR_ACTIVE.b, BACKGROUND_COLOR_ACTIVE.a)
    end
    otherCheckButton.MakeButtonInactive = function ()
        otherCheckButton.tex:SetColorTexture(BACKGROUND_COLOR.r, BACKGROUND_COLOR.g, BACKGROUND_COLOR.b, BACKGROUND_COLOR.a)
    end

    otherCheckButton:SetScript(
        "OnMouseDown",
        function()
            Private.mandatoryWAsWindow:Hide()
            Private.optionalWAsWindow:Hide()
            Private.auraCheckWindow:Hide()
            Private.otherCheckWindow:Show()
            mandatoryWAsButton:MakeButtonInactive()
            optionalWAsButton:MakeButtonInactive()
            auraCheckButton:MakeButtonInactive()
            otherCheckButton:MakeButtonActive()
        end
    )

    Private.WildThingsUI:AddBorder(otherCheckButton)
    otherCheckButton:SetBorderColor(borderColor.r, borderColor.g, borderColor.b)

    -- Sub windows
    Private.mandatoryWAsWindow = CreateFrame("Frame", nil, Private.window)
    Private.mandatoryWAsWindow:SetPoint("TOPLEFT", buttonFrame, "BOTTOMLEFT")
    Private.mandatoryWAsWindow:SetPoint("BOTTOMRIGHT", Private.window, "BOTTOMRIGHT")

    Private.optionalWAsWindow = CreateFrame("Frame", nil, Private.window)
    Private.optionalWAsWindow:SetPoint("TOPLEFT", buttonFrame, "BOTTOMLEFT")
    Private.optionalWAsWindow:SetPoint("BOTTOMRIGHT", Private.window, "BOTTOMRIGHT")

    Private.auraCheckWindow = CreateFrame("Frame", nil, Private.window)
    Private.auraCheckWindow:SetPoint("TOPLEFT", buttonFrame, "BOTTOMLEFT")
    Private.auraCheckWindow:SetPoint("BOTTOMRIGHT", Private.window, "BOTTOMRIGHT")

    Private.otherCheckWindow = CreateFrame("Frame", nil, Private.window)
    Private.otherCheckWindow:SetPoint("TOPLEFT", buttonFrame, "BOTTOMLEFT")
    Private.otherCheckWindow:SetPoint("BOTTOMRIGHT", Private.window, "BOTTOMRIGHT")

    Private.optionalWAsWindow:Hide()
    Private.auraCheckWindow:Hide()
    Private.otherCheckWindow:Hide()

    mandatoryWAsButton:MakeButtonActive()

    Private:InitializeSettings()

    -- When escape is pressed, close the main window
    Private.window:SetScript(
        "OnKeyDown",
        function(_, key)
            if InCombatLockdown() then return end

            if key == "ESCAPE" then
                Private.window:SetPropagateKeyboardInput(false)

                Private.window:Hide()
            else
                Private.window:SetPropagateKeyboardInput(true)
            end
        end
    )

    -- Mandatory WAs list
    mandatoryWAsList = Private:CreateMandatoryWAsList(Private.mandatoryWAsWindow, false)

    mandatoryWAsList:SetPoint("TOPLEFT", Private.mandatoryWAsWindow, "TOPLEFT", 4, -4)
    mandatoryWAsList:SetPoint("BOTTOMRIGHT", Private.mandatoryWAsWindow, "BOTTOMRIGHT", -1, 4)

    -- Optional WAs list
    optionalWAsList = Private:CreateMandatoryWAsList(Private.optionalWAsWindow, true)

    optionalWAsList:SetPoint("TOPLEFT", Private.optionalWAsWindow, "TOPLEFT", 4, -4)
    optionalWAsList:SetPoint("BOTTOMRIGHT", Private.optionalWAsWindow, "BOTTOMRIGHT", -1, 4)

    -- Aura check grid
    auraCheckGrid = Private:CreateAuraCheckGrid(Private.auraCheckWindow)

    auraCheckGrid:SetPoint("TOPLEFT", Private.auraCheckWindow, "TOPLEFT", 4, -4)
    auraCheckGrid:SetPoint("BOTTOMRIGHT", Private.auraCheckWindow, "BOTTOMRIGHT", -1, 4)

    -- Other check grid
    otherCheckGrid = Private:CreateOtherCheckGrid(Private.otherCheckWindow)

    otherCheckGrid:SetPoint("TOPLEFT", Private.otherCheckWindow, "TOPLEFT", 4, -4)
    otherCheckGrid:SetPoint("BOTTOMRIGHT", Private.otherCheckWindow, "BOTTOMRIGHT", -1, 4)

    Private:UpdateWindowResizeBounds()
end

-- function Private:WeakAuraImportCallback(id, btn)
--     if id then
--         -- Private:ReleaseUpdateFrame()
--         Private:InitializeInterfaceUpdate()
--     else
--         btn:SetDisabled(false)
--     end
-- end

-- function Private:WeakAuraCheckVersion(id)
--     local sameVersion = false
--     local addonVersion = nil
--     local savedVersion = nil

--     if WeakAurasSaved and WeakAurasSaved["displays"] and WeakAurasSaved["displays"][id] then
--         savedVersion = WeakAurasSaved["displays"][id].semver
--         local wa = Private:WeakAuraDeflate(Private.weakauraData[id])
--         if wa then
--             addonVersion = wa.d.semver
--             if DevTool then DevTool:AddData(wa) end
--             if addonVersion == savedVersion then
--                 sameVersion = true
--             else
--                 sameVersion = false
--             end
--         end
--     end

--     return addonVersion, savedVersion, sameVersion
-- end

-- function Private:WeakAuraDeflate(data)
--     local toDecode = data:match("!WA:2!(.+)")
--     if toDecode then
--         local decoded = LibDeflate:DecodeForPrint(toDecode)

--         if decoded then
--             local decompressed = LibDeflate:DecompressDeflate(decoded)

--             if decompressed then
--                 local success, data = LibSerialize:Deserialize(decompressed)

--                 if success then
--                     return data
--                 else
--                     print(string.format("could not deserialize aura data for [%s]", displayName))
--                     return
--                 end
--             else
--                 print(string.format("could not decompress aura data for [%s]", displayName))
--                 return
--             end
--         else
--             print(string.format("could not decode aura data for [%s]", displayName))
--             return
--         end
--     else
--         print(string.format("aura data for [%s] does not start with a valid prefix", displayName))
--         return
--     end
-- end
