local _, addonTable = ...
local core = addonTable
local TRANSLATE = core.TRANSLATE or function(msg) return msg end

core.GroupTab = core.GroupTab or {}
local GroupTab = core.GroupTab

local GROUP_LIST_HEADER_HEIGHT = core.GROUP_LIST_HEADER_HEIGHT or 36
local GROUP_LIST_ROWS_PADDING_X = core.GROUP_LIST_ROWS_PADDING_X or 4
local GROUP_LIST_ROW_HEIGHT = core.GROUP_LIST_ROW_HEIGHT or 36

function GroupTab.BuildList(owner, tabGroup, options)
    options = options or {}

    local tabKey = options.tabKey or "group"
    local applyPanelStyle = core.ApplyGroupRowsFrameStyle
    local createFrameWithTemplates = core.CreateFrameWithTemplateOptions
    local createHeaderFrame = core.CreateGroupHeaderFrame
    local layoutGroupListPanel = core.LayoutGroupListPanel
    if not (applyPanelStyle and createFrameWithTemplates and createHeaderFrame and layoutGroupListPanel) then
        return
    end

    local groupPreviewFrame = CreateFrame("Frame", nil, UIParent)
    groupPreviewFrame:ClearAllPoints()
    tabGroup:AddChild(groupPreviewFrame)
    groupPreviewFrame:SetFrameLevel((tabGroup.frame and tabGroup.frame:GetFrameLevel() or 0) + 1)
    groupPreviewFrame:Hide()
    applyPanelStyle(groupPreviewFrame)

    local itemList = CreateFrame("Frame", nil, groupPreviewFrame)
    itemList:SetFrameLevel(groupPreviewFrame:GetFrameLevel() + 1)

    local groupOuterInsetX = 6
    local groupListTopInset = 18
    local groupListBottomInset = 12
    local groupHeaderRowGap = 6
    local groupScrollBarWidth = 17
    local groupScrollBarXOffset = 19
    local groupScrollBarTopInset = 2
    local groupScrollBarBottomInset = 2
    local groupBrowseLeftOffset = groupOuterInsetX
    local groupBrowseTopOffset = -groupListTopInset
    local groupBrowseRightOffset = -groupOuterInsetX
    local groupBrowseBottomOffset = groupListBottomInset
    local groupBrowseCenterList = options.centerList == true
    local groupBrowseMaxWidth = tonumber(options.listMaxWidth)
    if groupBrowseCenterList and not groupBrowseMaxWidth and core.GetGroupColumnLayout then
        local columnLayout = core.GetGroupColumnLayout(options.columnWidths or core.GROUP_LIST_COLUMN_WIDTHS)
        groupBrowseMaxWidth = (columnLayout.totalWidth or 0) + (GROUP_LIST_ROWS_PADDING_X * 2)
    end

    itemList:ClearAllPoints()
    itemList:SetPoint("TOPLEFT", groupPreviewFrame, "TOPLEFT", groupBrowseLeftOffset, groupBrowseTopOffset)
    itemList:SetPoint("BOTTOMRIGHT", groupPreviewFrame, "BOTTOMRIGHT", groupBrowseRightOffset, groupBrowseBottomOffset)
    if itemList.SetClipsChildren then
        itemList:SetClipsChildren(false)
    end

    local headerContainer = CreateFrame("Frame", nil, itemList)
    headerContainer:SetFrameLevel(itemList:GetFrameLevel() + 1)
    itemList.HeaderContainer = headerContainer

    local scrollBox, scrollBoxTemplate = createFrameWithTemplates("Frame", nil, itemList, {
        "WowScrollBoxList",
        "WoWScrollBoxList",
    })
    local scrollBar, scrollBarTemplate = createFrameWithTemplates("EventFrame", nil, itemList, {
        "MinimalScrollBar",
    })
    if scrollBoxTemplate and scrollBarTemplate then
        scrollBox:SetFrameLevel(itemList:GetFrameLevel() + 1)
        scrollBar:SetFrameLevel(itemList:GetFrameLevel() + 2)
        itemList.ScrollBox = scrollBox
        itemList.ScrollBar = scrollBar
    else
        if scrollBox and scrollBox.Hide then
            scrollBox:Hide()
        end
        if scrollBar and scrollBar.Hide then
            scrollBar:Hide()
        end
    end
    itemList:Show()

    local groupHeaderParent = itemList.HeaderContainer or groupPreviewFrame
    if groupHeaderParent and groupHeaderParent.SetHeight then
        groupHeaderParent:SetHeight(GROUP_LIST_HEADER_HEIGHT)
    end

    local groupHeaderFrame = createHeaderFrame(groupPreviewFrame, {
        tabKey = tabKey,
        columnWidths = options.columnWidths,
        lastColumnText = options.lastColumnText,
    })
    groupHeaderFrame:SetParent(groupPreviewFrame)
    groupHeaderFrame:ClearAllPoints()
    groupHeaderFrame:SetPoint("TOPLEFT", itemList, "TOPLEFT", GROUP_LIST_ROWS_PADDING_X, 0)
    groupHeaderFrame:SetPoint("TOPRIGHT", itemList, "TOPRIGHT", -GROUP_LIST_ROWS_PADDING_X, 0)
    groupHeaderFrame:SetHeight(GROUP_LIST_HEADER_HEIGHT)
    groupHeaderFrame:SetFrameLevel(itemList:GetFrameLevel() + 2)
    groupHeaderFrame:Show()

    local groupEmpty = itemList:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    groupEmpty:SetText(TRANSLATE("GROUP.EMPTY.NO_SHARED_DATA"))
    if core.ApplyFont then
        core.ApplyFont(groupEmpty, 12, "")
    end

    local widgets
    local groupScrollBoxReady = false
    if itemList.ScrollBox and itemList.ScrollBar and ScrollUtil and CreateScrollBoxListLinearView then
        local view = CreateScrollBoxListLinearView(0, 0, GROUP_LIST_ROWS_PADDING_X, GROUP_LIST_ROWS_PADDING_X, 0)
        if view.SetElementExtent then
            view:SetElementExtent(GROUP_LIST_ROW_HEIGHT)
        end
        view:SetElementInitializer("Button", function(row, elementData)
            owner:InitializeGroupCharacterRowFrame(row)
            owner:ApplyGroupColumnWidthsToRow(widgets, row)
            if elementData and elementData.characterEntry then
                owner:RefreshGroupCharacterRowFrame(row, elementData.characterEntry, elementData.displayState)
            else
                owner:SetGroupRowFrameVisible(row, false)
            end
        end)
        ScrollUtil.InitScrollBoxListWithScrollBar(itemList.ScrollBox, itemList.ScrollBar, view)
        groupScrollBoxReady = true
    end

    widgets = {
        tabGroup = owner.widgets and owner.widgets.tabGroup or tabGroup,
        root = groupPreviewFrame,
        groupContainer = groupPreviewFrame,
        groupPreviewFrame = groupPreviewFrame,
        groupBrowseFrame = itemList,
        groupBrowseLeftOffset = groupBrowseLeftOffset,
        groupBrowseTopOffset = groupBrowseTopOffset,
        groupBrowseRightOffset = groupBrowseRightOffset,
        groupBrowseBottomOffset = groupBrowseBottomOffset,
        groupBrowseCenterList = groupBrowseCenterList,
        groupBrowseMaxWidth = groupBrowseMaxWidth,
        groupHeaderRowGap = groupHeaderRowGap,
        groupScrollBarWidth = groupScrollBarWidth,
        groupScrollBarXOffset = groupScrollBarXOffset,
        groupScrollBarTopInset = groupScrollBarTopInset,
        groupScrollBarBottomInset = groupScrollBarBottomInset,
        groupItemList = itemList,
        groupScrollBox = groupScrollBoxReady and itemList.ScrollBox or nil,
        groupScrollBar = groupScrollBoxReady and itemList.ScrollBar or nil,
        groupContent = groupScrollBoxReady and itemList.ScrollBox or groupPreviewFrame,
        groupEmpty = groupEmpty,
        groupHeaderFrame = groupHeaderFrame,
        groupRowsFrame = groupScrollBoxReady and itemList.ScrollBox or itemList,
        groupRowFrames = {},
        groupListKind = tabKey,
        groupBaseColumnWidths = options.columnWidths,
        groupEmptyText = options.emptyText,
    }

    owner.widgets = widgets
    owner.tabViews = owner.tabViews or {}
    owner.tabViews[tabKey] = widgets
    layoutGroupListPanel(widgets)

    if core.ApplyThemeToTabGroup then
        core.ApplyThemeToTabGroup(tabGroup)
    end
    if core.ApplyFontToFrame then
        core.ApplyFontToFrame(groupPreviewFrame)
    end
    groupPreviewFrame:Show()

    C_Timer.After(0, function()
        if owner.activeTab == tabKey and owner.widgets == widgets then
            layoutGroupListPanel(owner.widgets)
        end
    end)

    owner:RefreshMainWindow("BuildSelectedTab", tabKey)
end

function GroupTab.Build(owner, tabGroup)
    GroupTab.BuildList(owner, tabGroup, {
        tabKey = "group",
        centerList = true,
        emptyText = TRANSLATE("GROUP.EMPTY.NO_SHARED_DATA"),
    })
end
