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

local LibDeflate = LibStub:GetLibrary("LibDeflate")
local LibSerialize = LibStub:GetLibrary("LibSerialize")
local AceGUI = LibStub("AceGUI-3.0")

local frame = nil
local framePoint = "CENTER"
local frameRelativePoint = "CENTER"
local frameX = 0
local frameY = 0

function wt:Update()
    if frame then return end

    local colWidth = 300
    local fullWidth = colWidth * 2 + 20

    frame = AceGUI:Create("Frame")
    frame:SetWidth(fullWidth + 20)
    frame:SetHeight(350)
    frame:EnableResize(false)
    frame:SetTitle("Wild Things")
    frame:SetStatusText("WeakAura Updater")
    frame:SetLayout("Flow")
    frame:SetCallback("OnClose", function(widget)
        wt:ReleaseUpdateFrame()
    end)
    frame:SetPoint(framePoint, UIParent, frameRelativePoint, frameX, frameY)

    -- Keyboard handling: intercept ESC while allowing other keys
    frame.frame:EnableKeyboard(true)
    frame.frame:SetPropagateKeyboardInput(true)
    frame.frame:SetScript("OnKeyDown", function(self, key)
        if key == "ESCAPE" then
            self:SetPropagateKeyboardInput(false)
            wt:ReleaseAssignmentFrame()
        end
    end)
    frame.frame:SetScript("OnKeyUp", function(self)
        self:SetPropagateKeyboardInput(true)
    end)

    local label = AceGUI:Create("Label")
    label:SetText("Wild Things")
    label:SetWidth(fullWidth)
    label:SetFontObject(GameFontNormalHuge)
    label:SetImage(("Interface\\Addons\\%s\\Media\\Icons\\icon.tga"):format(AddonName))
    label:SetImageSize(20, 20)
    frame:AddChild(label)

    local function addHeading(text)
        local heading = AceGUI:Create("Heading")
        heading:SetFullWidth(true)
        heading:SetText(text)
        frame:AddChild(heading)
    end

    addHeading("Mandatory WAs")
    for _, id in ipairs(Private.WeakAuraMandatory) do
        wt:WeakAuraLine(id, colWidth, fullWidth)
    end

    addHeading("Optional WAs")
    for _, id in ipairs(Private.WeakAuraOptional) do
        wt:WeakAuraLine(id, colWidth, fullWidth)
    end

    addHeading("Options")
    -- Checkbox: "Open WeakAura Updater if new WeakAura Versions are available"
    local checkbox = AceGUI:Create("CheckBox")
    checkbox:SetType("checkbox")
    checkbox:SetFullWidth(true)
    checkbox:SetLabel("Auto open")
    checkbox:SetDescription("Automatically open the WeakAura Updater when new WeakAura versions are available upon login or after a UI reload.")
    checkbox:SetValue(wt.db.profile.update.auto_open)
    checkbox:SetCallback("OnValueChanged", function(widget, event, value)
        wt.db.profile.update.auto_open = value
    end)
    frame:AddChild(checkbox)
end

function wt:ReleaseUpdateFrame()
    if not frame then return end

    local point, _, relativePoint, x, y = frame:GetPoint(1)
    framePoint = point
    frameRelativePoint = relativePoint
    frameX = x
    frameY = y

    frame:ReleaseChildren()
    AceGUI:Release(frame)
    frame = nil
end

function wt:WeakAuraLine(id, colWidth, fullWidth)
    if not frame then return end

    local addonVersion, savedVersion, sameVersion = wt:WeakAuraCheckVersion(id)

    local grp = AceGUI:Create("SimpleGroup")
    grp:SetLayout("Flow")
    grp:SetWidth(fullWidth)
    grp:SetHeight(100)
    frame:AddChild(grp)

    local txt = AceGUI:Create("Label")
    txt:SetText(id)
    txt:SetWidth(colWidth)
    txt:SetFontObject(GameFontNormalLarge)
    grp:AddChild(txt)

    local txt = AceGUI:Create("Label")
    if savedVersion and not sameVersion then
        --Update
        txt:SetText("|cffff5555" .. savedVersion .. "|r > |cff55ff55" .. addonVersion .. "|r")
    elseif sameVersion then
        --Up to date
        txt:SetText(savedVersion)
        txt:SetColor(0.3, 1.0, 0.3)
    else
        --Install
        txt:SetText("Not Installed")
        txt:SetColor(0.5, 0.5, 0.5)
    end
    txt:SetWidth(colWidth/2)
    txt:SetFontObject(GameFontNormalLarge)
    grp:AddChild(txt)


    local btn = AceGUI:Create("Button")
    btn:SetWidth(colWidth/2)
    btn:SetCallback("OnClick", function()
        if WeakAuras then
            btn:SetDisabled(true)
            WeakAuras.Import(Private.weakauraData[id], Private.weakauraData[id]["uid"], function(id) wt:WeakAuraImportCallback(id, btn) end)
        end
    end)
    if savedVersion and not sameVersion then
        btn:SetText("Update")
    elseif sameVersion then
        btn:SetDisabled(true)
        btn:SetText("Up to date")
    else
        btn:SetText("Install")
    end
    grp:AddChild(btn)
end

function wt:WeakAuraImportCallback(id, btn)
    if id then
        wt:ReleaseUpdateFrame()
        wt:Update()
    else
        btn:SetDisabled(false)
    end
end

function wt: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 = wt: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 wt: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
