-- AuraShare.lua
local _, PUP = ...
local AceComm = LibStub("AceComm-3.0")
local LibSerialize = LibStub("LibSerialize")
local LibDeflate = LibStub("LibDeflate")
local del = ":"

local infoText = nil;

function PUP:InitializeAuraShare()
    -- Titel
    local title = PUP.shareWindow:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    title:SetPoint("CENTER", PUP.shareWindow, "CENTER", 0, 24)
    title:SetText("WeakAura teilen")

    -- EditBox
    local edit = CreateFrame("EditBox", "PUP_AuraStringBox", PUP.shareWindow, "InputBoxTemplate")
    edit:SetMultiLine(false)
    edit:SetFontObject(PUFont17)  
    edit:SetPoint("TOPLEFT", PUP.shareWindow, "TOPLEFT", 16, -48)
    edit:SetPoint("BOTTOMRIGHT", PUP.shareWindow, "BOTTOMRIGHT", -16, 48)
    edit:SetAutoFocus(false)
    edit:SetScript("OnEscapePressed", edit.ClearFocus)
    PUP.shareWindow.editBox = edit

    -- Infotext
    infoText = PUP.shareWindow:CreateFontString(nil, "OVERLAY", "GameFontWhiteSmall")
    infoText:SetPoint("CENTER", PUP.shareWindow, "CENTER", 0, -24)
    infoText:SetText("")

    -- Send-Button
    local sendBtn = PUP:CreateButton(PUP.shareWindow, "Senden", function()
        PUP:SendWeakAuraString(edit:GetText())
    end)
    sendBtn:SetPoint("BOTTOMRIGHT", PUP.shareWindow, "BOTTOMRIGHT", -16, 16)

    -- Clear-Button
    local clearBtn = PUP:CreateButton(PUP.shareWindow, "Leeren", function()
        edit:SetText("")
        infoText:SetText("")
        edit:SetFocus()
    end)
    clearBtn:SetPoint("BOTTOMLEFT", PUP.shareWindow, "BOTTOMLEFT", 16, 16)
end


local function Broadcast(event, channel, ...)
    local message = event
    local argTable = {...}

    local argCount = #argTable

    for i = 1, argCount do
        local functionArg = argTable[i]
        local argType = type(functionArg)

        if argType == "table" then
            functionArg = LibSerialize:Serialize(functionArg)
            functionArg = LibDeflate:CompressDeflate(functionArg)
            functionArg = LibDeflate:EncodeForWoWAddonChannel(functionArg)
            message = string.format("%s"..del.."%s(%s)", message, tostring(functionArg), argType)
        elseif argType == "string" then
            functionArg = LibDeflate:CompressDeflate(functionArg)
            functionArg = LibDeflate:EncodeForWoWAddonChannel(functionArg)
            message = string.format("%s"..del.."%s(%s)", message, tostring(functionArg), argType)
        else
            if argType ~= "string" and argType ~= "number" and argType ~= "boolean" then
                functionArg = ""
                argType = "string"
            end
            message = string.format("%s"..del.."%s(%s)", message, tostring(functionArg), argType)
        end
    end
    AceComm:SendCommMessage("PUP_MSG", message, channel)
end

local function EventHandler(e, ...) -- internal checks whether the event comes from addon comms. We don't want to allow blizzard events to be fired manually
    if e == "PLAYER_REGEN_ENABLED" then
        C_Timer.After(1, function()
            if PUP.WAString and PUP.WAString.unit and PUP.WAString.string then
                EventHandler("PUP_WA_SHARE", PUP.WAString.unit, PUP.WAString.string)
                PUP.WAString = nil
            end
        end)
    elseif e == "PUP_WA_SHARE" then
        local unit, str = ...
        if UnitExists(unit) and not UnitIsUnit("player", unit) then
            if UnitAffectingCombat("player") or WeakAuras.CurrentEncounter then
                PUP.WAString = {unit = unit, string = str}
            else
                PUP:ShowPopupWindow(unit.." möchte dir eine WeakAura senden. Importieren?", 
                    function() 
                        WeakAuras.Import(str) 
                    end, 
                    0, 
                    0, 
                    false, 
                    "Importieren")
            end
        end
    elseif e == "ENCOUNTER_END" then    
        C_Timer.After(1, function()
            if PUP.WAString and PUP.WAString.unit and PUP.WAString.string then
                EventHandler("PUP_WA_SHARE", PUP.WAString.unit, PUP.WAString.string)
            end
        end)
    end
end

function PUP:SendWeakAuraString(str)
    if not str or str == "" then
        infoText:SetText("Keinen WeakAura-String eingegeben!")
        return
    end
    if not IsInRaid() then
        infoText:SetText("WeakAura-String wird nur über Raid gesendet!")
        return
    end 
    Broadcast("PUP_WA_SHARE", "RAID", str)
    infoText:SetText("WeakAura-String gesendet über RAID.")
end

local function ReceiveComm(text, sender)
    local argTable = {strsplit(del, text)}
    local event = argTable[1]
    if (UnitExists(sender) and (UnitInRaid(sender) or UnitInParty(sender))) then -- block addon msg's from outside the raid, only exception being a the guild nickname comms. 
        local formattedArgTable = {sender}
        table.remove(argTable, 1)

        local tonext
        for i, functionArg in ipairs(argTable) do
            local argValue, argType = functionArg:match("(.*)%((%a+)%)")
            if tonext and argValue then argValue = tonext..argValue end
            if argType == "number" then
                argValue = tonumber(argValue)
                tonext = nil
            elseif argType == "boolean" then
                argValue = argValue == "true"
                tonext = nil
            elseif argType == "string" then
                argValue = LibDeflate:DecodeForWoWAddonChannel(argValue)
                argValue = LibDeflate:DecompressDeflate(argValue)
            elseif argType == "table" then
                argValue = LibDeflate:DecodeForWoWAddonChannel(argValue)
                argValue = LibDeflate:DecompressDeflate(argValue)
                local success, table = LibSerialize:Deserialize(argValue)
                if success then
                    argValue = table
                else
                    argValue = ""
                end
                tonext = nil
            end
            if argValue and argType then
                if argValue == "" then
                    table.insert(formattedArgTable, false)
                else
                    table.insert(formattedArgTable, argValue)
                end
                tonext = nil
            end
            if not argType then
                tonext = tonext or ""
                tonext = tonext..functionArg..del -- if argtype wasn't given then this is part of a table that was falsely split by the delimeter so we're stitching it back together
            end
        end
        EventHandler(event, unpack(formattedArgTable))
        WeakAuras.ScanEvents(event, unpack(formattedArgTable))
    end
end



AceComm:RegisterComm("PUP_MSG", function(_, text, _, sender) ReceiveComm(text, sender) end)

local f = CreateFrame("Frame")
f:RegisterEvent("ENCOUNTER_END")
f:RegisterEvent("PLAYER_REGEN_ENABLED")

f:SetScript("OnEvent", function(self, e, ...)
    EventHandler(e, ...)
end)


