local G={}local N=require(script:FindFirstAncestor("\080\108\117\103\105\110\070\114\097\109\101\119\111\114\107"))local x local n local h local O local X local f local j=Color3.fromRGB(255,255,255)local function w(G)return G:find("\114\098\120\097\115\115\101\116")end local function k(G)local N=G.groups local n=G.scale local h={}local k=0 local function I()k=k+1 end for G,N in pairs(N)do if N.isVisible then I()local G=("\071\114\111\117\112\095\037\115"):format(N.name)local x=N.icon or X.Icons.Unknown h[G]=O:Get(X.RoactWidgetLine.Type.Group,{name=N.name;nameColor=N.nameColor,isOpen=N.isOpen;totalMacros=#N.macros;icon=x;iconColor=N.iconColor or j,isIconImageId=w(x);layoutOrder=k;scale=n})if N.isOpen then for G,x in pairs(N.macros)do if x.isVisible then I()local G=("\071\114\111\117\112\095\037\115\095\077\097\099\114\111\095\037\115"):format(N.name,x.name)local q=x.macro.Icon or X.Icons.Unknown h[G]=O:Get(X.RoactWidgetLine.Type.Macro,{name=x.name;nameColor=x.macro.NameColor;isOpen=x.isOpen,icon=q;iconColor=x.macro.IconColor or j,isIconImageId=w(q);layoutOrder=k;scale=n,macro=x.macro,macroScript=x.moduleScript;isBroken=x.isBroken,isLocalMacro=x.isLocalMacro})if x.isOpen then local G=#x.macro.Fields>0 if G or not f:GetSetting("\072\105\100\101\085\110\117\115\101\100\070\105\101\108\100\115\065\110\100\075\101\121\098\105\110\100")then I()local f=("\071\114\111\117\112\095\037\115\095\077\097\099\114\111\095\037\115\095\070\105\101\108\100\115"):format(N.name,x.name)h[f]=O:Get(X.RoactWidgetLine.Type.Fields,{isOpen=x.isFieldsOpen;macroScript=x.moduleScript;hasFields=G;layoutOrder=k;scale=n})if G and x.isFieldsOpen then for G,f in pairs(x.macro.Fields)do I()local j=("\071\114\111\117\112\095\037\115\095\077\097\099\114\111\095\037\115\095\070\105\101\108\100\095\037\115"):format(N.name,x.name,f.Name)h[j]=O:Get(X.RoactWidgetLine.Type.Field,{field=f,macro=x.macro;layoutOrder=k;scale=n})end end end local j=x.macro.Keybind or{}if#j>0 or not f:GetSetting("\072\105\100\101\085\110\117\115\101\100\070\105\101\108\100\115\065\110\100\075\101\121\098\105\110\100")then I()local G=("\071\114\111\117\112\095\037\115\095\077\097\099\114\111\095\037\115\095\075\101\121\098\105\110\100"):format(N.name,x.name)h[G]=O:Get(X.RoactWidgetLine.Type.Keybind,{keybind=j,isDisabled=x.macro.State.IsKeybindDisabled;layoutOrder=k;scale=n})end I()local w=("\071\114\111\117\112\095\037\115\095\077\097\099\114\111\095\037\115\095\083\101\116\116\105\110\103\115"):format(N.name,x.name)h[w]=O:Get(X.RoactWidgetLine.Type.Settings,{moduleScript=x.moduleScript,layoutOrder=k;scale=n,macro=x.macro})end end end end end end I()local q=("\066\111\116\116\111\109\080\097\100\100\105\110\103"):format()h[q]=x.createElement("\070\114\097\109\101",{LayoutOrder=k,BackgroundTransparency=1,Size=UDim2.new(1,0,0,X.RoactWidgetLine.Pixel.BottomPaddingHeight)})return x.createFragment(h)end function G.Get(N,G)return x.createElement("\083\099\114\111\108\108\105\110\103\070\114\097\109\101",{BackgroundTransparency=1,Size=UDim2.fromScale(1,1);CanvasSize=UDim2.new(0,0,0,0);AutomaticCanvasSize=Enum.AutomaticSize.Y,ScrollBarThickness=6,BorderSizePixel=0},{UIPadding=x.createElement("\085\073\080\097\100\100\105\110\103",{PaddingBottom=UDim.new(0,4),PaddingLeft=UDim.new(0,4),PaddingRight=UDim.new(0,10);PaddingTop=UDim.new(0,4)}),UIListLayout=x.createElement("\085\073\076\105\115\116\076\097\121\111\117\116",{FillDirection=Enum.FillDirection.Vertical;SortOrder=Enum.SortOrder.LayoutOrder}),Lines=k(G)})end function G.FrameworkInit(G)x=N:Require("\082\111\097\099\116")n=N:Require("\082\111\097\099\116\082\111\100\117\120")h=N:Require("\083\111\099\107\101\116\067\111\110\115\116\097\110\116\115")O=N:Require("\082\111\097\099\116\077\097\099\114\111\076\105\110\101\115")X=N:Require("\087\105\100\103\101\116\067\111\110\115\116\097\110\116\115")f=N:Require("\083\111\099\107\101\116\083\101\116\116\105\110\103\115")end function G.FrameworkStart(G) end return G
---
---Roact stuff for all the macros
---
---@class RoactMacroContainer
---
local RoactMacroContainer = {}

--------------------------------------------------
-- Types
-- ...

--------------------------------------------------
-- Dependencies
local PluginFramework = require(script:FindFirstAncestor("PluginFramework")) ---@type Framework
local Roact ---@type Roact
local RoactRodux ---@type RoactRodux
local SocketConstants ---@type SocketConstants
local RoactMacroLines ---@type RoactMacroLines
local WidgetConstants ---@type WidgetConstants
local SocketSettings ---@type SocketSettings

--------------------------------------------------
-- Constants
local COLOR_WHITE = Color3.fromRGB(255, 255, 255)

--------------------------------------------------
-- Members

---@param str string
---@return boolean
local function couldStringBeIconImageId(str)
    return str:find("rbxasset")
end

---Creates all of the individual lines to populate the MacroContainer
---@param props table
---@return RoactFragment
local function createLinesFragment(props)
    -- Grab variables
    local groups = props.groups ---@type RoactMainWidgetProps.GroupInfo[]
    local scale = props.scale ---@type number
    local elements = {}
    local layoutOrderCount = 0

    local function increaseLayoutOrder()
        layoutOrderCount = layoutOrderCount + 1
    end

    for _, groupInfo in pairs(groups) do
        if groupInfo.isVisible then
            -- Create group line
            increaseLayoutOrder()
            local groupElementName = ("Group_%s"):format(groupInfo.name)
            local groupIcon = groupInfo.icon or WidgetConstants.Icons.Unknown
            elements[groupElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Group, {
                name = groupInfo.name,
                nameColor = groupInfo.nameColor,
                isOpen = groupInfo.isOpen,
                totalMacros = #groupInfo.macros,
                icon = groupIcon,
                iconColor = groupInfo.iconColor or COLOR_WHITE,
                isIconImageId = couldStringBeIconImageId(groupIcon),
                layoutOrder = layoutOrderCount,
                scale = scale,
            })

            if groupInfo.isOpen then
                -- Create macros
                for _, macroInfo in pairs(groupInfo.macros) do
                    if macroInfo.isVisible then
                        -- Create macro line
                        increaseLayoutOrder()
                        local macroElementName = ("Group_%s_Macro_%s"):format(groupInfo.name, macroInfo.name)
                        local macroIcon = macroInfo.macro.Icon or WidgetConstants.Icons.Unknown
                        elements[macroElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Macro, {
                            name = macroInfo.name,
                            nameColor = macroInfo.macro.NameColor,
                            isOpen = macroInfo.isOpen,
                            icon = macroIcon,
                            iconColor = macroInfo.macro.IconColor or COLOR_WHITE,
                            isIconImageId = couldStringBeIconImageId(macroIcon),
                            layoutOrder = layoutOrderCount,
                            scale = scale,
                            macro = macroInfo.macro,
                            macroScript = macroInfo.moduleScript,
                            isBroken = macroInfo.isBroken,
                            isLocalMacro = macroInfo.isLocalMacro,
                        })

                        -- Create child lines
                        if macroInfo.isOpen then
                            -- Create fields line
                            local hasFields = #macroInfo.macro.Fields > 0
                            if hasFields or not SocketSettings:GetSetting("HideUnusedFieldsAndKeybind") then
                                increaseLayoutOrder()
                                local fieldsElementName = ("Group_%s_Macro_%s_Fields"):format(groupInfo.name, macroInfo.name)
                                elements[fieldsElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Fields, {
                                    isOpen = macroInfo.isFieldsOpen,
                                    macroScript = macroInfo.moduleScript,
                                    hasFields = hasFields,
                                    layoutOrder = layoutOrderCount,
                                    scale = scale,
                                })

                                -- Create individual fields
                                if hasFields and macroInfo.isFieldsOpen then
                                    for _, field in pairs(macroInfo.macro.Fields) do
                                        increaseLayoutOrder()
                                        local fieldElementName = ("Group_%s_Macro_%s_Field_%s"):format(
                                            groupInfo.name,
                                            macroInfo.name,
                                            field.Name
                                        )
                                        elements[fieldElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Field, {
                                            field = field,
                                            macro = macroInfo.macro,
                                            layoutOrder = layoutOrderCount,
                                            scale = scale,
                                        })
                                    end
                                end
                            end

                            -- Create keybind line
                            local keybindTuple = macroInfo.macro.Keybind or {}
                            if #keybindTuple > 0 or not SocketSettings:GetSetting("HideUnusedFieldsAndKeybind") then
                                increaseLayoutOrder()
                                local keybindElementName = ("Group_%s_Macro_%s_Keybind"):format(groupInfo.name, macroInfo.name)
                                elements[keybindElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Keybind, {
                                    keybind = keybindTuple,
                                    isDisabled = macroInfo.macro.State.IsKeybindDisabled,
                                    layoutOrder = layoutOrderCount,
                                    scale = scale,
                                })
                            end

                            -- Create setting line
                            increaseLayoutOrder()
                            local settingsElementName = ("Group_%s_Macro_%s_Settings"):format(groupInfo.name, macroInfo.name)
                            elements[settingsElementName] = RoactMacroLines:Get(WidgetConstants.RoactWidgetLine.Type.Settings, {
                                moduleScript = macroInfo.moduleScript,
                                layoutOrder = layoutOrderCount,
                                scale = scale,
                                macro = macroInfo.macro,
                            })
                        end
                    end
                end
            end
        end
    end

    -- Create bottom padding
    increaseLayoutOrder()
    local paddingElementName = ("BottomPadding"):format()
    elements[paddingElementName] = Roact.createElement("Frame", {
        LayoutOrder = layoutOrderCount,
        BackgroundTransparency = 1,
        Size = UDim2.new(1, 0, 0, WidgetConstants.RoactWidgetLine.Pixel.BottomPaddingHeight),
    })

    return Roact.createFragment(elements)
end

---
---@param props table
---@return RoactElement
---
function RoactMacroContainer:Get(props)
    return Roact.createElement("ScrollingFrame", {
        BackgroundTransparency = 1,
        Size = UDim2.fromScale(1, 1),
        CanvasSize = UDim2.new(0, 0, 0, 0),
        AutomaticCanvasSize = Enum.AutomaticSize.Y,
        ScrollBarThickness = 6,
        BorderSizePixel = 0,
    }, {
        UIPadding = Roact.createElement("UIPadding", {
            PaddingBottom = UDim.new(0, 4),
            PaddingLeft = UDim.new(0, 4),
            PaddingRight = UDim.new(0, 10),
            PaddingTop = UDim.new(0, 4),
        }),
        UIListLayout = Roact.createElement("UIListLayout", {
            FillDirection = Enum.FillDirection.Vertical,
            SortOrder = Enum.SortOrder.LayoutOrder,
        }),
        Lines = createLinesFragment(props),
    })
end

---
---@private
---
---Asynchronously called with all other FrameworkInit()
---
function RoactMacroContainer:FrameworkInit()
    Roact = PluginFramework:Require("Roact")
    RoactRodux = PluginFramework:Require("RoactRodux")
    SocketConstants = PluginFramework:Require("SocketConstants")
    RoactMacroLines = PluginFramework:Require("RoactMacroLines")
    WidgetConstants = PluginFramework:Require("WidgetConstants")
    SocketSettings = PluginFramework:Require("SocketSettings")
end

---
---@private
---
---Synchronously called, one after the other, with all other FrameworkStart()
---
function RoactMacroContainer:FrameworkStart() end

return RoactMacroContainer
