--[[
Author: Jarth
Filename: CBs_Constants.lua
]] --
-------------------------------------------------------------------------------------------------
-- VARIABLES --
-------------------------------------------------------------------------------------------------
CollectionBars = {
    WM = GetWindowManager(),
    Addon = {Name = "CollectionBars", DisplayName = "Collection Bars", Abbreviation = "CBs", Version = 1.1, MinorVersion = 6, SettingsSlash = "/cb", Author = "Jarth"},
    AllButtons = {},
    Default = {
        UseAccountSettings = true,
        Bar = {Depth = 5, Width = 0, SnapSize = 5},
        Button = {Size = ZO_GAMEPAD_ACTION_BUTTON_SIZE, IsAudioEnabled = true, IsActiveActivationEnabled = true},
        Scene = {OnHud = true, OnHudUI = true, InMenu = true, InInventory = false, InInteract = false, InBank = false, InFence = false, InStore = false},
        Bindings = {
            Show = true,
            [1] = 0,
            [2] = 0,
            [3] = 0,
            [4] = 0,
            [5] = 0,
            [6] = 0,
            [7] = 0,
            [8] = 0,
            [9] = 0,
            [10] = 0,
            [11] = 0,
            [12] = 0,
            [13] = 0,
            [14] = 0,
            [15] = 0,
            [16] = 0,
            [17] = 0,
            [18] = 0,
            [19] = 0,
            [20] = 0
        },
        Combine = {
            Bar = {Depth = 0, Width = 0, Offset = {X = CENTER, Y = CENTER}},
            Label = {Show = true, Display = "CombineBar", Offset = {X = 0, Y = 0}, Position = BOTTOMLEFT, PositionTarget = TOPLEFT}
        },
        Categories = {},
        Logging = {Info = false, Debug = false, Verbose = false}
    },
    Global = {
        EnableSettings = false,
        IsMoveEnabled = false,
        ReverseBindings = {},
        Settings = {
            Frame = nil,
            List = nil,
            Filters = {["Categories"] = "Categories", ["Collectibles"] = "Collectibles", ["Category"] = "Category", ["General"] = "General", ["Combined"] = "Combined bar"}
        },
        Combine = {Name = "Combine", EventTS = nil, Frames = {Frame = nil, Move = nil}, category = nil, HideAll = nil, Fragment = nil, IsEmpty = false},
        ChoiceLocations = {"top", "topright", "right", "bottomright", "bottom", "bottomleft", "left", "topleft", "center"},
        AvailableFonts = {"ZoFontGameSmall", "ZoFontGameLarge", "ZoFontGameLargeBold", "ZoFontGameLargeBoldShadow", "ZoFontHeader", "ZoFontHeader2", "ZoFontHeader3", "ZoFontHeader4"},
        Scenes = {
            [1] = {Name = "OnHud", Instance = HUD_SCENE, Description = "%s on main view/hud"},
            [2] = {Name = "OnHudUI", Instance = HUD_UI_SCENE, Description = "%s on the main view when an overlay is activated/hudui"},
            [3] = {Name = "InMenu", Instance = SCENE_MANAGER:GetScene("gameMenuInGame"), Description = "%s in menu"},
            [4] = {Name = "InInventory", Instance = SCENE_MANAGER:GetScene("inventory"), Description = "%s in the inventory"},
            [5] = {Name = "InInteract", Instance = SCENE_MANAGER:GetScene("interact"), Description = "%s in interactions"},
            [6] = {Name = "InBank", Instance = SCENE_MANAGER:GetScene("bank"), Description = "%s at a bank"},
            [7] = {Name = "InFence", Instance = SCENE_MANAGER:GetScene("fence_keyboard"), Description = "%s at a fence"},
            [8] = {Name = "InStore", Instance = SCENE_MANAGER:GetScene("store"), Description = "%s at a store"}
        },
        HighestUnlocked = 0,
        ShowChildren = {Appearance = true}
    },
    Categories = {},
    CategoriesOrdered = {},
    Texts = {
        Font = {ZoFontWinT1 = "ZoFontWinT1", ZoFontWinH4 = "ZoFontWinH4"},
        Format = {Number = "%.2f", Decimal = "%d", Comma = "%s,%s"},
        Location = {
            Bottom = "bottom",
            BottomLeft = "bottomleft",
            BottomRight = "bottomright",
            Center = "center",
            Left = "left",
            Right = "right",
            Top = "top",
            TopLeft = "topleft",
            TopRight = "topright"
        },
        Settings = {ToggleMoveFrameText = "Toggle move frame", ReloadText = "Reload list of 'Collectibles'\nHint: Usefull after gaining a new collectible)"}
    },
    Loggers = {}
}
local base = CollectionBars

base.Texts.FormatAbbreviation = string.format("%s%%s", base.Addon.Abbreviation)
base.Texts.FormatAbbreviationLowDash = string.format("%s_%%s", base.Addon.Abbreviation)
base.Texts.FormatCategoryName = string.format("%s_C%%s", base.Addon.Abbreviation)
base.Texts.FormatBindingName = string.format("SI_BINDING_NAME_%s", base.Texts.FormatAbbreviationLowDash)
base.Texts.CombineFrameName = string.format(base.Texts.FormatAbbreviationLowDash, "CombineFrame")
base.Texts.CombineFrameNameHideAll = string.format("%s%s", base.Texts.CombineFrameName, "HideAll")
base.Texts.AccountKey = string.format("%s_Account", base.Addon.Name)
base.Texts.CharacterKey = string.format("%s_Character", base.Addon.Name)

-------------------------------------------------------------------------------------------------
-- FUNCTIONS --
-------------------------------------------------------------------------------------------------

function base:GenerateCategories()
    base:Debug("GenerateCategories")
    base.Categories = {}

    for _, categoryData in ZO_COLLECTIBLE_DATA_MANAGER:CategoryIterator({ZO_CollectibleCategoryData.HasShownCollectiblesInCollection}) do
        if categoryData ~= nil and categoryData:IsStandardCategory() then
            local type = base.GetType(categoryData)
            if type ~= nil and categoryData ~= nil and base:CategoryHasUnlockedValidAndUsableCollectible(categoryData) then
                base.AddCategory(type, categoryData)
            else
                if categoryData:IsTopLevelCategory() and base:SubCategoryHasUsableCollectible(categoryData) then
                    local parentIcons = {categoryData:GetKeyboardIcons()}
                    base.AddCategory(nil, categoryData, parentIcons, true)
                    for _, subcategoryData in categoryData:SubcategoryIterator({ZO_CollectibleCategoryData.HasShownCollectiblesInCollection}) do
                        type = base.GetType(subcategoryData)
                        if type ~= nil and subcategoryData ~= nil and subcategoryData:HasShownCollectiblesInCollection() then
                            base.AddCategory(type, subcategoryData, parentIcons, false, categoryData:GetFormattedName())
                        end
                    end
                end
            end
        end
    end
end

function base.GetType(categoryData)
    base:Debug("GetType", categoryData)
    local type = nil
    local collectibles = categoryData:GetCollectibleDataBySpecializedSort()
    if collectibles ~= nil and collectibles[1] ~= nil then type = collectibles[1]:GetCategoryType() end

    return type
end

function base.AddCategory(type, categoryData, parentIcons, hasChildren, parentKey)
    base:Debug("AddCategory", type, categoryData, parentIcons, hasChildren, parentKey)
    local categoryName = categoryData:GetFormattedName()
    local categoryId = categoryData:GetId()
    local icon = parentIcons or {categoryData:GetKeyboardIcons()}
    if icon ~= nil and icon[1] == ZO_NO_TEXTURE_FILE then icon = nil end
    base.Categories[categoryId] = {
        Collection = {},
        CollectionOrdered = {},
        Buttons = {},
        Type = type,
        Id = categoryId,
        CategoryData = categoryData,
        Icon = icon,
        HasChildren = hasChildren,
        ParentKey = parentKey,
        Unlocked = 0,
        Name = categoryName,
        Frames = {Frame = nil, Label = nil, LabelButton = nil, ToggleSettings = nil, Move = nil},
        Bar = {Depth = 0, Width = nil},
        Cooldown = {Event = string.format("Cooldown%s", categoryName), CollectibleId = nil, StartTime = nil, Tick = 100},
        Fragment = nil
    }
    table.insert(base.CategoriesOrdered, base.Categories[categoryId])
    base.Default.Categories[categoryId] = {
        AutoSelectAll = false,
        Selected = {},
        Enabled = false,
        Tooltip = {Show = true, Position = TOP},
        Bar = {IsCombined = true, HideAll = true, Depth = 0, Width = 0, Horizontal = true, Offset = {X = CENTER, Y = CENTER}},
        Menu = {ShowDisabled = false},
        Label = {Show = true, EnableHideAll = true, Display = categoryName, Offset = {X = 0, Y = 0}, Height = 19, Width = 75, Font = "ZoFontGameSmall", Position = BOTTOMLEFT, PositionTarget = TOPLEFT}
    }
end

function base:CategoryHasUnlockedValidAndUsableCollectible(categoryData)
    base:Debug("CategoryHasUnlockedValidAndUsableCollectible", categoryData)
    if GetTotalCollectiblesByCategoryType(categoryData:GetId()) > 0 then
        for _, collectibleData in ZO_CollectibleCategoryData.CollectibleIterator(categoryData, {ZO_CollectibleData.IsShownInCollection}) do
            if collectibleData:IsUnlocked() and collectibleData:IsValidForPlayer() and collectibleData:IsUsable() then return true end
        end
    end
    return false
end

function base:SubCategoryHasUsableCollectible(categoryData)
    base:Debug("SubCategoryHasUsableCollectible", categoryData)
    for _, subcategoryData in categoryData:SubcategoryIterator({ZO_CollectibleCategoryData.HasShownCollectiblesInCollection}) do
        local type = base.GetType(subcategoryData)
        if type ~= nil and subcategoryData ~= nil and base:CategoryHasUnlockedValidAndUsableCollectible(subcategoryData) then return true end
    end
    return false
end