local _AddonName, _EchoRaidTools = ...
local _Cooldowns = _EchoRaidTools:GetModule("cooldowns")

local LibContainer = LibStub:GetLibrary("LibContainer")
local LibColorNames = LibStub:GetLibrary("LibColorNames")
local LibSharedMedia = LibStub:GetLibrary ("LibSharedMedia-3.0")

local noop = function() end

local spacing = 2

_Cooldowns.controlPools = {}
_Cooldowns.controls = {}
_Cooldowns.sections = {}
_Cooldowns.preSettings = {lines = {}}
_Cooldowns.RefreshAllSettings = function()
    _Cooldowns.mainPanel.Header.HeaderText:SetText("Cooldowns - Group - ".._Cooldowns.GetCurrentGroupName())
    _Cooldowns.sectionBuilders.StatesSettingsConfigSection()
    for i, lineDetails in ipairs(_Cooldowns.preSettings.lines) do
        for ii, control in ipairs(lineDetails.controls) do
            control:Update()
        end
        lineDetails.line:Update()
    end
    for i, sectionDetails in ipairs(_Cooldowns.sections) do
        local sectionHeight = 30
        for ii, lineDetails in ipairs(sectionDetails.lines) do
            for iii, control in ipairs(lineDetails.controls) do
                control:Update()
            end
            lineDetails.line:Update()
            if lineDetails.line.type == "line" and not lineDetails.line.IsHidden then
                sectionHeight = sectionHeight + lineDetails.line:GetHeight()
            end
        end
        sectionDetails.section:Update()
        if sectionDetails.section.Button.contentHeight ~= sectionHeight then
            sectionDetails.section.Button.contentHeight = sectionHeight
            if not sectionDetails.section.IsHidden and sectionDetails.section.Button.Expanded then
                local _, r, rp, x, y = sectionDetails.section.ContentPanel:GetPointByName("TOPLEFT")
                sectionDetails.section.ContentPanel:SetPoint("BOTTOMLEFT", r, rp, x, -sectionHeight)
            end
        end
    end

end
_Cooldowns.RefreshSections = function()
    for i, section in ipairs(_Cooldowns.sections) do
        section.section:Update()
    end
end

local ScrollInToView = function(value)
    local top = _EchoRaidTools.moduleButtons[1]:GetTop()
    _EchoRaidTools.panels.main.MainMenu.ScrollFrame:ScrollFrameIntoView(value, top)
end

local displayResetFunc = function(pool, control)
    control:ClearAllPoints()
    control:Hide()
    control.Update = noop
    control.tooltip = nil
    if control.type == "CHECKBUTTON" then
        control.CheckButton:SetScript("OnClick", nil)
    elseif control.type == "SLIDER" then
        control.Slider:SetScript("OnValueChanged", nil)
        control.ValueEditbox:SetScript("OnEnterPressed", nil)
    elseif control.type == "TEXTEDIT" then
        control:SetGetter(nil)
        control:SetSetter(nil)
    elseif control.type == "BUTTON" then
        control.Button:SetScript("OnClick", nil)
    elseif control.type == "EDITBOX" then
        control.Editbox:SetScript("OnEnterPressed", nil)
    elseif control.type == "LONGEDITBOX" then
        control.Editbox:SetScript("OnEnterPressed", nil)
    elseif control.type == "SECTION" then
        --if control.Button.Expanded then
        --    control.Button:Toggle()
            control.Button.contentHeight = nil
        --end
    elseif control.type == "DROPDOWN" then
        control:ClearSelections()
    elseif control.type == "COLOR" then
        control:ClearAll()
    elseif control.type == "LINE" then
        control.textRight = nil
    elseif control.type == "SubButton" then
        control:SetOnClick(noop)
        control:SetSelected(false)
        control:SetLoaded(true)
        --control:SetGroupDisabled(false)
        control.filterIndex = nil
        control.groupIndex = nil
        control:SetSetter(noop)
        control:SetGetter(noop)
        control:SetUseCheckButton(false)
        control:SetDeleteFunc(noop)
        control:SetCopyFunc(noop)
        control:SetCheckButtonSetter(noop)
        control:SetCheckButtonGetter(noop)
    end
end


local BuildControlTypeCreators = function()
    local mainContainer = _Cooldowns.controlParent
    _Cooldowns.controlTypesCreators = {
        ["CHECKBUTTON"] = function(details, parent)
            if not _Cooldowns.controlPools["CHECKBUTTON"] then
                _Cooldowns.controlPools["CHECKBUTTON"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_CheckButton", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["CHECKBUTTON"]:Acquire()
            control.type = "CHECKBUTTON"
            control:SetParent(parent)
            control:Show()
            control:SetHeight(32)
            control:SetWidth(details.width or 32)
            control.TopText:SetText(details.text)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            control.CheckButton:SetScript("OnClick", details.onClick)
            control.CheckButton:SetChecked(details.valueFunc())
            control.tooltip = details.tooltip
            control.CheckButton.tooltip = details.tooltip
            function control:Update()
                control.CheckButton:SetChecked(details.valueFunc())
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["DROPDOWN"] = function(details, parent, index)
            if not _Cooldowns.controlPools["DROPDOWN"] then
                _Cooldowns.controlPools["DROPDOWN"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_Dropdown", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["DROPDOWN"]:Acquire()
            control.type = "DROPDOWN"
            control:SetParent(parent)
            control.tooltip = details.tooltip
            control.TopText:SetText(details.text)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            if details.width then
                control:SetWidth(max(150,details.width))
            else
                control:SetWidth(200)
            end
            control:Show()
            --local items = details.items()
            --control:SetupSelections(items, details.valueFunc())

            function control:Update()
                local items = details.items()
                local selected = details.valueFunc()
                control:SetupSelections(items, selected)
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["SLIDER"] = function(details, parent, index)
            if not _Cooldowns.controlPools["SLIDER"] then
                _Cooldowns.controlPools["SLIDER"] = CreateFramePool("FRAME", mainContainer, "EchoRaidTools_BetterSlider", displayResetFunc)--"EchoRaidToolsConfig_Slider" EchoRaidTools_BetterSlider
            end
            local control = _Cooldowns.controlPools["SLIDER"]:Acquire()
            control.type = "SLIDER"
            control:SetParent(parent)
            control.TopText:SetText(details.text)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            control.tooltip = details.tooltip
            control.Slider.tooltip = details.tooltip
            control.ValueEditbox.tooltip = details.tooltip
            control:Show()
            control:SetHeight(32)
            control:SetWidth(details.width or 200)
            control:Setup(details.min, details.max, details.step, details.valueFunc, details.func, details.hardMin, details.hardMax)

            function control:Update()
                control:UpdateValues()
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["COLOR"] = function(details, parent, index)
            if not _Cooldowns.controlPools["COLOR"] then
                _Cooldowns.controlPools["COLOR"] = CreateFramePool("BUTTON", mainContainer, "EchoRaidToolsConfig_NewColorPicker", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["COLOR"]:Acquire()
            control.type = "COLOR"
            control:SetParent(parent)
            control:Show()
            control:SetWidth(details.width or 80)
            control.tooltip = details.tooltip
            local col = details.GetColor()
            local r,g,b,a = col:GetRGBA()
            control:SetupInteraction(details.SetColor, r,g,b,a)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            function control:Update()
                local col = details.GetColor()
                local r,g,b,a = col:GetRGBA()
                control:SetupInteraction(details.SetColor, r,g,b,a)
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end

            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["TEXT"] = function(details, parent, index)
            if not _Cooldowns.controlPools["TEXT"] then
                _Cooldowns.controlPools["TEXT"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_TextOnly", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["TEXT"]:Acquire()
            control.type = "TEXT"
            control:SetParent(parent)
            control:Show()
            control.Text:SetText(details.text)
            control.tooltip = details.tooltip
            function control:Update()
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["TEXTEDIT"] = function(details, parent, index)
            if not _Cooldowns.controlPools["TEXTEDIT"] then
                _Cooldowns.controlPools["TEXTEDIT"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_EditableText", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["TEXTEDIT"]:Acquire()
            control.type = "TEXTEDIT"
            control:SetParent(parent)
            control:Show()
            control:SetHeight(32)
            local width = details.width or 200
            control:SetWidth(max(width, 100))
            control.Button:SetText(details.valueFunc())
            control.Button:Show()
            control:SetGetter(details.valueFunc)
            control:SetSetter(details.setterFunc)
            control.TopText:SetText(details.text)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            control.tooltip = details.tooltip
            control.Button.tooltip = details.tooltip
            control.EditBox.tooltip = details.tooltip
            function control:Update()
                control.Button:SetText(details.valueFunc())
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["BUTTON"] = function(details, parent, index)
            if not _Cooldowns.controlPools["BUTTON"] then
                _Cooldowns.controlPools["BUTTON"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_Button", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["BUTTON"]:Acquire()
            control.type = "BUTTON"
            control:SetParent(parent)
            control:Show()
            control:SetHeight(32)
            control:SetWidth(details.width or 200)
            control.Button:SetText(details.textFunc())
            control.Button:Show()
            control.Button:SetScript("OnClick", details.onClick)
            control.TopText:SetText(details.text)
            if details.color then
                control.Button:GetHighlightTexture():SetVertexColor(details.color.r,details.color.g,details.color.b,details.color.a)
            end
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            control.tooltip = details.tooltip
            control.Button.tooltip = details.tooltip
            function control:Update()
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["EDITBOX"] = function(details, parent, index)
            if not _Cooldowns.controlPools["EDITBOX"] then
                _Cooldowns.controlPools["EDITBOX"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_EditBox", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["EDITBOX"]:Acquire()
            control.type = "EDITBOX"
            control:SetParent(parent)
            control.TopText:SetText(details.text)
            if details.useTopText then
                control.TopText:Show()
            else
                control.TopText:Hide()
            end
            control.tooltip = details.tooltip
            control.Editbox.tooltip = details.tooltip
            control:Show()
            control:SetHeight(32)
            control:SetWidth(details.width or 80)
            control.Editbox:SetText(details.valueFunc())
            control.Editbox:SetScript("OnEnterPressed", function(self)
                local textValue = self:GetText()
                local value = tonumber(textValue)
                if value and value ~= details.valueFunc() then
                    details:func(value)
                else
                    self:ClearFocus()
                end
            end)
            function control:Update()
                control.Editbox:SetText(details.valueFunc())
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["LINE"] = function(details, parent, index)
            if not _Cooldowns.controlPools["LINE"] then
                _Cooldowns.controlPools["LINE"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_LineTitle", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["LINE"]:Acquire()
            control:SetParent(parent)
            control:Show()
            control.Text:SetText(type(details.lineTitle) == "function" and details.lineTitle() or details.lineTitle)
            control:SetWidth(200)
            if details.textRight then
                control.Text:SetJustifyH("RIGHT")
            end
            if details.tooltip then
                control.Info:Show()
                control.Info.tooltip = details.tooltip
            end
            control.tooltip = details.tooltip
            function control:Update()
                control.Text:SetText(type(details.lineTitle) == "function" and details.lineTitle() or details.lineTitle)
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    control:SetHidden(details.SetHidden())
                end
            end
            control.type = "line"
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["ANCHORDEMO"] = function(details, parent, index)
            if not _Cooldowns.controlPools["ANCHORDEMO"] then
                _Cooldowns.controlPools["ANCHORDEMO"] = CreateFramePool("FRAME", mainContainer, "EchoRaidTools_TextAnchorDemo", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["ANCHORDEMO"]:Acquire()
            control.type = "ANCHORDEMO"
            control:SetParent(parent)
            control:Show()
            control:Anchor(details.GetAnchorDetails())
            --control:Setup(details.displayType)
            function control:Update()
                control:Anchor(details.GetAnchorDetails())
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["SPELLBUTTON"] = function(details, parent, index)
            if not _Cooldowns.controlPools["SPELLBUTTON"] then
                _Cooldowns.controlPools["SPELLBUTTON"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_FilterSpellButton", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["SPELLBUTTON"]:Acquire()
            control.type = "SPELLBUTTON"
            control:SetParent(parent)
            control:Show()
            control:SetText(details.spellName)
            control:SetClass(details.class)
            control:SetupClick(details.onClick)
            control:SetIcon(details.icon)

            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["SEARCHBOX"] = function(details, parent, index)
            if not _Cooldowns.controlPools["SEARCHBOX"] then
                _Cooldowns.controlPools["SEARCHBOX"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_Cooldowns_SpellSearchBox", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["SEARCHBOX"]:Acquire()
            control.type = "SEARCHBOX"
            control:SetParent(parent)
            control:Show()
            control.tooltip = details.tooltip
            control:SetWidth(details.width or 200)

            function control:Update()
                control:SetFuncs(details.func)
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end

            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["INFO"] = function(details, parent, index)
            if not _Cooldowns.controlPools["INFO"] then
                _Cooldowns.controlPools["INFO"] = CreateFramePool("FRAME", mainContainer, "EchoRaidTools_InfoButton", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["INFO"]:Acquire()
            control.type = "INFO"
            if details.color then
                local c = details.color
                control.Texture:SetDesaturated(true)
                control.Texture:SetVertexColor(c.r, c.g, c.b, c.a)
            else
                control.Texture:SetDesaturated(false)
                control.Texture:SetVertexColor(1,1,1,1)
            end
            control:SetParent(parent)
            control:Show()
            control.tooltip = details.tooltip
            function control:Update()
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end

            _Cooldowns.controls[details.name] = control
            return control
        end,
        ["SEPARATOR"] = function(details, parent, index)
            if not _Cooldowns.controlPools["SEPARATOR"] then
                _Cooldowns.controlPools["SEPARATOR"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsConfig_Separator", displayResetFunc)
            end
            local control = _Cooldowns.controlPools["SEPARATOR"]:Acquire()
            control.type = "SEPARATOR"
            control:SetParent(parent)
            control:Show()
            function control:Update()
                if details.SetDisabled then
                    if details.SetDisabled() then
                        control:Disable()
                    else
                        control:Enable()
                    end
                end
                if details.SetHidden then
                    if details.SetHidden() then
                        control:Hide()
                    else
                        control:Show()
                    end
                end
            end
            _Cooldowns.controls[details.name] = control
            return control
        end,
    }
end

_Cooldowns.sectionBuilders = _Cooldowns.sectionBuilders or {}
_Cooldowns.RebuildConfig = function()
    local controlTypesCreators = _Cooldowns.controlTypesCreators
    for _, pool in pairs(_Cooldowns.controlPools) do
        pool:ReleaseAll()
    end
    wipe(_Cooldowns.controls)
    wipe(_Cooldowns.sections)
    wipe(_Cooldowns.preSettings.lines)
    local mainContainer = _Cooldowns.controlParent

    if not _Cooldowns.controlPools["SECTION"] then
        _Cooldowns.controlPools["SECTION"] = CreateFramePool("FRAME", mainContainer, "EchoRaidToolsCollapsableConfig", displayResetFunc)
    end

    _Cooldowns.SectionButtons = _Cooldowns.SectionButtons or {}

    local lastSection = nil
    for _, containerSettings in ipairs(_Cooldowns.settings) do

        local sectionDetails = type(containerSettings) == "function" and containerSettings() or containerSettings
        local section = _Cooldowns.controlPools["SECTION"]:Acquire()
        section.type = "SECTION"
        section:Show()
        table.insert(_Cooldowns.sections, {section = section, lines = {}})
        local sectionTable = _Cooldowns.sections[#_Cooldowns.sections]
        if lastSection then
            section:SetPoint("TOPLEFT", lastSection.ContentPanel, "BOTTOMLEFT", 0, 0)
            section:SetPoint("TOPRIGHT", lastSection.ContentPanel, "BOTTOMRIGHT", 0, 0)
        else
            mainContainer.TopSection = section
            section:SetPoint("TOPLEFT", mainContainer, 0, -10)-- -preSettingsHeight)
            section:SetPoint("TOPRIGHT", mainContainer, "TOPRIGHT", 0, -10) -- -preSettingsHeight) 
        end
        section.Button.ButtonText:SetText(sectionDetails.label)
        section.Update = function()
            if sectionDetails.SetHidden then
                section:SetHidden(sectionDetails:SetHidden())
            end
        end
        _Cooldowns.SectionButtons[sectionDetails.name] = section
        lastSection = section

        _Cooldowns.sectionBuilders[sectionDetails.name] = _Cooldowns.sectionBuilders[sectionDetails.name] or function()
            local thisSection = section
            for i, lineDetails in ipairs(sectionTable.lines) do
                for j, control in ipairs(lineDetails.controls) do
                    _Cooldowns.controlPools[control.type]:Release(control)
                end
                _Cooldowns.controlPools["LINE"]:Release(lineDetails.line)
            end
            wipe(sectionTable.lines)
            local sectionDetails = type(containerSettings) == "function" and containerSettings() or containerSettings

            local lastLine = nil
            for i, lineDetails in ipairs(sectionDetails.contents) do
                local newLine = controlTypesCreators["LINE"](lineDetails, thisSection.ContentPanel, i)

                newLine.name = lineDetails.name
                --section.ContentPanel[lineDetails.name] = newLine
                table.insert(sectionTable.lines, {line = newLine, controls = {}})
                local lineTable = sectionTable.lines[#sectionTable.lines]
                if lastLine then
                    newLine:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, 0)
                else
                    newLine:SetPoint("TOPLEFT", thisSection.ContentPanel, 25, -25)
                end
                newLine:SetHidden(false)
                lastLine = newLine

                local lineAvailableWidth = 650
                local currentLineWidth = 0
                local multiLineHeight = 0
                local lineHeight = 0
                local lastControl
                for j, controlDetails in ipairs(lineDetails.contents) do
                    local control = controlTypesCreators[controlDetails.type](controlDetails, lastLine, j)
                    control.name = controlDetails.name
                    table.insert(lineTable.controls, control)
                    local controlHeight = control:GetHeight()
                    controlHeight = controlDetails.useTopText and controlHeight + 6 or controlHeight
                    if currentLineWidth + control:GetWidth() > lineAvailableWidth then
                        currentLineWidth = 0
                        multiLineHeight = multiLineHeight + lineHeight
                        lineHeight = 0
                        control:SetPoint("TOPLEFT", lastLine, "TOPRIGHT", 20,  - multiLineHeight)
                        currentLineWidth = control:GetWidth()
                    elseif lastControl then
                        control:SetPoint("LEFT", lastControl, "RIGHT", controlDetails.padding or 20, 0)
                    else
                        control:SetPoint("TOPLEFT", lastLine, "TOPRIGHT", 20, 0)--16)
                    end
                    currentLineWidth = currentLineWidth + control:GetWidth() + (controlDetails.padding or 20)

                    lineHeight = max(lineHeight, controlHeight)
                    lastControl = control
                end
                newLine:SetHeight(lineHeight + multiLineHeight + (lineDetails.padding or 12))
            end
        end
        _Cooldowns.sectionBuilders[sectionDetails.name]()
    end
    _Cooldowns.RefreshAllSettings()

    mainContainer.preSettings = _Cooldowns.preSettings
    mainContainer.sections = _Cooldowns.sections
end

function _Cooldowns.ShowFilters(filterIndex)
    _Cooldowns.currentFilterIndex = filterIndex
    _Cooldowns.filtersPanel.Header.HeaderText:SetText("Cooldowns - Filter - ".. _Cooldowns.customFilters.GetFilterName(filterIndex))
    local filtersMainContainer = _Cooldowns.filtersControlParent
    local controlTypesCreators = _Cooldowns.controlTypesCreators
    _Cooldowns.FilterControls = _Cooldowns.FilterControls or {}
    for control, pool in pairs(_Cooldowns.FilterControls) do
        pool:Release(control)
    end
    wipe(_Cooldowns.FilterControls)

    local lastLine

    local filterSettings = _Cooldowns.GetFilterSettings(filterIndex)
    for i, lineDetails in ipairs(filterSettings.contents) do
        local newLine = controlTypesCreators["LINE"](lineDetails, filtersMainContainer, i)
        _Cooldowns.FilterControls[newLine] = _Cooldowns.controlPools["LINE"]

        newLine.name = lineDetails.name
        if lastLine then
            newLine:SetPoint("TOPLEFT", lastLine, "BOTTOMLEFT", 0, 0)
        else
            newLine:SetPoint("TOPLEFT", filtersMainContainer, 25, -25)
        end
        newLine:SetHidden(false)
        lastLine = newLine

        local lineAvailableWidth = 950
        local currentLineWidth = 0
        local multiLineHeight = 0
        local lineHeight = 0
        local lastControl
        for j, controlDetails in ipairs(lineDetails.contents) do
            local control = controlTypesCreators[controlDetails.type](controlDetails, lastLine, j)
            _Cooldowns.FilterControls[control] = _Cooldowns.controlPools[controlDetails.type]
            control:Update()
            control.name = controlDetails.name
            local controlHeight = control:GetHeight()
            controlHeight = controlDetails.useTopText and controlHeight + 6 or controlHeight
            if currentLineWidth + control:GetWidth() > lineAvailableWidth then
                currentLineWidth = 0
                multiLineHeight = multiLineHeight + lineHeight
                lineHeight = 0
                control:SetPoint("TOPLEFT", lastLine, "TOPLEFT", 20,  - multiLineHeight)
                currentLineWidth = control:GetWidth()
            elseif lastControl then
                control:SetPoint("LEFT", lastControl, "RIGHT", controlDetails.padding or 20, 0)
            else
                control:SetPoint("TOPLEFT", lastLine, "TOPLEFT", 20, 0)--16)
            end
            currentLineWidth = currentLineWidth + control:GetWidth() + (controlDetails.padding or 20)

            lineHeight = max(lineHeight, controlHeight)
            lastControl = control
        end
        newLine:SetHeight(lineHeight + multiLineHeight + (lineDetails.padding or 12))
    end
    _Cooldowns.mainPanel:Hide()
    _Cooldowns.filtersPanel:Show()
    _Cooldowns.RebuildNavigation()
end

function _Cooldowns:GetCooldownsConfig()
    if _EchoRaidTools.panels.cooldowns then
        return _EchoRaidTools.panels.cooldowns
    end

    --main panel creation
    local window = CreateFrame("FRAME", nil, _EchoRaidTools.panels.main, "EchoRaidTools_CooldownsWindow")

    local panel = CreateFrame("FRAME", nil, window, "EchoRaidTools_CooldownsPanel")
    panel:SetAllPoints()
    panel.Header.HeaderText:SetText("Cooldowns")
    local mainContainer = panel.ScrollFrame.ScrollingPanel
    _Cooldowns.mainPanel = panel

    _Cooldowns.controlParent = mainContainer
    if not _Cooldowns.controlTypesCreators then
        BuildControlTypeCreators()
    end

    _Cooldowns.RebuildConfig()
    panel.ScrollFrame:SetVerticalScroll(0)

    local Resize = function() end
    panel:SetScript("OnSizeChanged", Resize)

    -- filter panels
    local filtersPanel = CreateFrame("FRAME", nil, window, "EchoRaidTools_CooldownsPanel")
    filtersPanel:SetAllPoints()
    filtersPanel.Header.HeaderText:SetText("Cooldowns - Custom Filter")
    local filtersMainContainer = filtersPanel.ScrollFrame.ScrollingPanel
    _Cooldowns.filtersPanel = filtersPanel

    _Cooldowns.filtersControlParent = filtersMainContainer
    filtersPanel.ScrollFrame:SetVerticalScroll(0)
    filtersPanel:SetScript("OnSizeChanged", Resize)
    filtersPanel:Hide()

    _EchoRaidTools.panels.cooldowns = window

    return window
end

function _Cooldowns.RebuildNavigation()
    local buttonFrame = _Cooldowns.NavigationButtons
    if not buttonFrame then return end

    for control, pool in pairs(_Cooldowns.NavigationControls) do
        pool:Release(control)
        _Cooldowns.NavigationControls[control] = nil
    end
    local sections = buttonFrame.children

    local GroupButton = sections.groups
    local GroupParent = GroupButton.ChildFrame

    if not _Cooldowns.NavigationControlPools["SubBUTTON"] then
        _Cooldowns.NavigationControlPools["SubBUTTON"] = CreateFramePool("FRAME", buttonFrame, "EchoRaidTools_MainMenu_SubButton", displayResetFunc)
    end

    local childHeight = 0
    local lastControl
    local spacing = 2
    for groupIndex, details in ipairs(EchoRaidToolsDB.Cooldowns.groups) do
        local control = _Cooldowns.NavigationControlPools["SubBUTTON"]:Acquire()
        _Cooldowns.NavigationControls[control] = _Cooldowns.NavigationControlPools["SubBUTTON"]
        control.type = "SubBUTTON"
        control:SetParent(GroupParent)
        control:SetHeight(25)
        control:SetWidth(200)
        control:SetText(details.name)
        control:Show()
        control.groupIndex = groupIndex
        control:SetOnClick(function()
            _Cooldowns.SetCurrentGroup(groupIndex)
            if _Cooldowns.filtersPanel:IsShown() then
                _Cooldowns.filtersPanel:Hide()
                _Cooldowns.mainPanel:Show()
            end
            _Cooldowns.RebuildNavigation()
        end)
        control:SetGetter(function(self) return _Cooldowns.GetGroupName(groupIndex) end)
        control:SetSetter(function(self,text) _Cooldowns.RenameGroup(text, groupIndex) end)
        control:SetDeleteFunc(function()
            _Cooldowns.DeleteGroup(groupIndex)
            _Cooldowns.RefreshAllSettings()
            _Cooldowns.RebuildNavigation()
        end)
        control:SetCopyFunc(function()
            _Cooldowns.CopyGroup(groupIndex)
            if _Cooldowns.filtersPanel:IsShown() then
                _Cooldowns.filtersPanel:Hide()
                _Cooldowns.mainPanel:Show()
            end
            _Cooldowns.RebuildNavigation()
            ScrollInToView(GroupParent:GetBottom())
        end)
        control:SetSelected(
            _Cooldowns.GetCurrentGroupIndex() == groupIndex 
            and (
                (_Cooldowns.mainPanel and _Cooldowns.mainPanel:IsShown()) 
                or
                (not (_Cooldowns.filtersPanel and _Cooldowns.filtersPanel:IsShown()))
            )
        )
        control:SetLoaded(_Cooldowns.IsGroupLoaded(groupIndex))
        --control:SetGroupDisabled(not _Cooldowns.IsGroupActive(groupIndex))
        control:SetCheckButtonSetter(function() _Cooldowns.ToggleGroup(groupIndex) end)
        control:SetCheckButtonGetter(function() return _Cooldowns.IsGroupActive(groupIndex) end)
        control:SetUseCheckButton(true)
        control:ClearAllPoints()
        if lastControl then
            control:SetPoint("TOPLEFT", lastControl, "BOTTOMLEFT")
            control:SetPoint("TOPRIGHT", lastControl, "BOTTOMRIGHT")
        else
            control:SetPoint("TOPLEFT", GroupParent, "TOPLEFT", 22, -spacing)
            control:SetPoint("TOPRIGHT", GroupParent, "TOPRIGHT", 0, -spacing)
        end
        lastControl = control
        childHeight = childHeight + control:GetHeight()-- + spacing
    end
    GroupButton.childHeight = childHeight
    GroupButton:SetupHeight()

    local FiltersButton = sections.filters
    local FiltersParent = FiltersButton.ChildFrame

    local childHeight = 0
    local lastControl = nil
    for filterIndex, customFilterDetails in ipairs(_Cooldowns.GetCustomFilters()) do
        local control = _Cooldowns.NavigationControlPools["SubBUTTON"]:Acquire()
        _Cooldowns.NavigationControls[control] = _Cooldowns.NavigationControlPools["SubBUTTON"]
        control.type = "SubBUTTON"
        control:SetParent(FiltersParent)
        control:SetHeight(25)
        control:SetWidth(200)
        control:SetText(customFilterDetails.name)
        control:Show()
        control.filterIndex = filterIndex
        control:SetGetter(function() return _Cooldowns.customFilters.GetFilterName(filterIndex) end)
        control:SetSetter(function(self, text)
            _Cooldowns.customFilters.Rename(filterIndex, text)
        end)
        control:SetDeleteFunc(function()
            _Cooldowns.customFilters.Delete(filterIndex)
            if _Cooldowns.customFilters.GetNumFilters() > 0 then
                _Cooldowns.ShowFilters(1)
            else
                if _Cooldowns.filtersPanel:IsShown() then
                    _Cooldowns.filtersPanel:Hide()
                    _Cooldowns.mainPanel:Show()
                end
            end
            _Cooldowns.RebuildNavigation()
        end)
        control:SetCopyFunc(function()
            _Cooldowns.customFilters.Copy(filterIndex)
            local newFilterIndex = _Cooldowns.customFilters.GetNumFilters()
            _Cooldowns.ShowFilters(newFilterIndex)
            ScrollInToView(FiltersParent:GetBottom())
        end)
        control:SetOnClick(function()
            _Cooldowns.ShowFilters(filterIndex)
            --[[local sectionButton = _Cooldowns.SectionButtons["FilterConfigSection"].Button
            local frame = _Cooldowns.controls["filter_"..filterIndex.."Line"]
            local top = _Cooldowns.mainPanel.ScrollFrame.ScrollingPanel.TopSection.Button:GetTop()
            if sectionButton and frame then
                if not sectionButton:IsExpanded() then
                    sectionButton:Toggle()
                end
                RunNextFrame(function()_Cooldowns.mainPanel.ScrollFrame:ScrollFrameIntoView(frame, top) end)
            end]]
        end)
        control:SetSelected(_Cooldowns.filtersPanel and _Cooldowns.filtersPanel:IsShown() and filterIndex == _Cooldowns.currentFilterIndex)
        control:SetLoaded(true)
        control:SetUseCheckButton(false)
        control:ClearAllPoints()
        if lastControl then
            control:SetPoint("TOPLEFT", lastControl, "BOTTOMLEFT")
            control:SetPoint("TOPRIGHT", lastControl, "BOTTOMRIGHT")
        else
            control:SetPoint("TOPLEFT", FiltersParent, "TOPLEFT", 22, -spacing)
            control:SetPoint("TOPRIGHT", FiltersParent, "TOPRIGHT", 0, -spacing)
        end
        lastControl = control
        childHeight = childHeight + control:GetHeight()-- + spacing
    end
    FiltersButton.childHeight = childHeight
    FiltersButton:SetupHeight()

    buttonFrame:UpdateHeight()
end

function _Cooldowns:GetNavigationButtons()
    if _Cooldowns.NavigationButtons then
        return _Cooldowns.NavigationButtons
    end

    -- create the buttons frame
    local NavigationButtons = CreateFrame("FRAME", nil, _EchoRaidTools.panels.main.MainMenu)
    _Cooldowns.NavigationButtons = NavigationButtons
    function NavigationButtons:UpdateHeight()
        self.children = self.children or {}
        local currentHeight = 0
        for _, section in pairs(self.children) do
            currentHeight = currentHeight + section.height
        end
        self.height = currentHeight
        if self:IsShown() then
            local p, r, rp, x, y = self:GetPointByName("TOPLEFT")
            self:SetPoint("BOTTOMLEFT", r, rp, x, -self.height)
        end
    end
    _Cooldowns.NavigationControls = _Cooldowns.NavigationControls or {}
    _Cooldowns.NavigationControlPools = _Cooldowns.NavigationControlPools or {}
    _Cooldowns.NavigationButtons.children = _Cooldowns.NavigationButtons.children or {}
    local buttonFrame = _Cooldowns.NavigationButtons
    if not _Cooldowns.NavigationControlPools["SubExpand"] then
        _Cooldowns.NavigationControlPools["SubExpand"] = CreateFramePool("FRAME", buttonFrame, "EchoRaidTools_MainMenu_ExpandButton", displayResetFunc)
    end

    local GroupButton = _Cooldowns.NavigationControlPools["SubExpand"]:Acquire()
    GroupButton.type = "SubExpand"
    GroupButton:SetParent(buttonFrame)
    GroupButton:Show()
    GroupButton:SetHeight(25)
    GroupButton:SetWidth(200)
    GroupButton:SetText("Groups")
    GroupButton:SetPoint("TOPLEFT", buttonFrame, "TOPLEFT", 0, 0)
    GroupButton:SetPoint("TOPRIGHT", buttonFrame, "TOPRIGHT", 0, 0)
    GroupButton:SetAddFunc(function()
        _Cooldowns.AddNewGroup()
        if _Cooldowns.filtersPanel:IsShown() then
            _Cooldowns.filtersPanel:Hide()
            _Cooldowns.mainPanel:Show()
        end
        _Cooldowns.RebuildNavigation()
        ScrollInToView(GroupButton.ChildFrame:GetBottom())
    end)
    GroupButton.parent = buttonFrame
    buttonFrame.children.groups = GroupButton
    local GroupParent = GroupButton.ChildFrame

    local FiltersButton = _Cooldowns.NavigationControlPools["SubExpand"]:Acquire()
    FiltersButton.type = "SubExpand"
    FiltersButton:SetParent(buttonFrame)
    FiltersButton:Show()
    FiltersButton:SetHeight(25)
    FiltersButton:SetWidth(200)
    FiltersButton:SetAddFunc(function()
        _Cooldowns.customFilters.Add()
        local newFilterIndex = _Cooldowns.customFilters.GetNumFilters()
        _Cooldowns.ShowFilters(newFilterIndex)
        _Cooldowns.RebuildNavigation()
        ScrollInToView(FiltersButton.ChildFrame:GetBottom())
    end)
    FiltersButton:SetText("Filters")
    FiltersButton:SetPoint("TOPLEFT", GroupParent, "BOTTOMLEFT", 0, 0)
    FiltersButton:SetPoint("TOPRIGHT", GroupParent, "BOTTOMRIGHT", 0, 0)
    FiltersButton.parent = buttonFrame
    buttonFrame.children.filters = FiltersButton

    _Cooldowns.RebuildNavigation()
    GroupButton:Toggle()
    FiltersButton:Toggle()

    return NavigationButtons
end

function _Cooldowns:GetButtonInfo()
    return "Cooldowns",
     nil,
     function()
        return _Cooldowns:GetCooldownsConfig()
    end,
    _Cooldowns:GetNavigationButtons()
end

