local addonName, addon = ...

local UI = addon.UI
local LT = addon.LootTracker
local LootDB = LT.DB
local Crafting = LT.Crafting
local Data = LT.Data
local Query = LT.Query
local PriceSource = LT.PriceSource
local Upgrade = LT.Upgrade

------------------------------------------------------------
-- CONSTANTS
------------------------------------------------------------

local WINDOW_WIDTH = 820
local WINDOW_HEIGHT = 650

local HEADER_HEIGHT = 48
local ITEM_HEIGHT = 78

local BODY_GAP = 10
local PADDING = 14

local REAGENT_PANEL_WIDTH = 500
local SUMMARY_PANEL_WIDTH = 270

local REAGENT_ROW_HEIGHT = 72
local SHOP_ROW_HEIGHT = 42

------------------------------------------------------------
-- SMALL HELPERS
------------------------------------------------------------

local function CopyTable(source)
    if type(source) ~= "table" then
        return source
    end

    local result = {}

    for key, value in pairs(source) do
        result[CopyTable(key)] =
            CopyTable(value)
    end

    return result
end

local function SafeText(value, fallback)
    if value == nil
        or value == ""
    then
        return fallback or ""
    end

    return tostring(value)
end

local function ClearTooltip()
    GameTooltip:Hide()
end

local function CreatePanel(
    parent
)
    local panel =
        CreateFrame(
            "Frame",
            nil,
            parent,
            "BackdropTemplate"
        )

    panel:SetBackdrop({
        bgFile =
            "Interface\\Buttons\\WHITE8X8",

        edgeFile =
            "Interface\\Buttons\\WHITE8X8",

        edgeSize = 1,
    })

    panel:SetBackdropColor(
        0.045,
        0.045,
        0.060,
        0.96
    )

    panel:SetBackdropBorderColor(
        unpack(
            UI.COLORS.border
        )
    )

    return panel
end

local function CreateSectionTitle(
    parent,
    text
)
    local title =
        parent:CreateFontString(
            nil,
            "OVERLAY"
        )

    title:SetFontObject(
        GameFontNormalLarge
    )

    title:SetText(
        text
    )

    title:SetTextColor(
        unpack(
            UI.COLORS.gold
        )
    )

    return title
end

local function GetSlotTitle(slot)
    local title =
        slot.slotText

    if title
        and title ~= ""
    then
        return title
    end

    if slot.qualitySlot then
        return UI:T("MATERIAL_QUALITY", "MATERIAL QUALITY")
    end

    if slot.selectableRequired then
        return UI:T("REQUIRED_CHOICE", "REQUIRED CHOICE")
    end

    if slot.optional then
        return UI:T("OPTIONAL_REAGENT", "OPTIONAL REAGENT")
    end

    return UI:T("REAGENT", "REAGENT")
end

local function GetSelection(
    plan,
    slot
)
    return plan.selections[
        tostring(
            slot.dataSlotIndex
        )
    ]
end

local function GetSelectedReagent(
    plan,
    slot
)
    local selection =
        GetSelection(
            plan,
            slot
        )

    if not selection then
        return nil
    end

    return {
        itemID =
            selection.itemID,

        currencyID =
            selection.currencyID,

        qualityID =
            selection.qualityID,
    }
end

------------------------------------------------------------
-- CRAFTED CATALOG
------------------------------------------------------------

function UI:GetCraftedCatalog()
    local slotID =
        self.LootSlotID == -1
        and nil
        or self.LootSlotID

    local character =
        self:GetLootTrackerCharacter()

    local classID =
        character
        and character.classID
        or nil

    return Crafting:GetProfessionRecipeOptions(
        classID,
        self.LootSpecID,
        slotID,
        self.LootCraftType or "ALL"
    )
end

------------------------------------------------------------
-- CRAFTED BROWSE
------------------------------------------------------------

function UI:BuildCraftedBrowse()
    local content =
        self.LootContent

    local options,
        errorCode =
        self:GetCraftedCatalog()

    if #options == 0 then
        local panel =
            CreatePanel(
                content
            )

        panel:SetSize(
            1060,
            120
        )

        panel:SetPoint(
            "TOPLEFT",
            content,
            "TOPLEFT",
            0,
            0
        )

        local title =
            CreateSectionTitle(
                panel,
                self:T("CRAFTED_GEAR", "CRAFTED GEAR")
            )

        title:SetPoint(
            "TOPLEFT",
            panel,
            "TOPLEFT",
            14,
            -14
        )

        local text =
            panel:CreateFontString(
                nil,
                "OVERLAY"
            )

        text:SetFontObject(
            GameFontNormal
        )

        text:SetPoint(
            "TOPLEFT",
            title,
            "BOTTOMLEFT",
            0,
            -10
        )

        text:SetWidth(
            810
        )

        text:SetJustifyH(
            "LEFT"
        )

        text:SetWordWrap(
            true
        )

        if errorCode ==
            "PROFESSION_DB_EMPTY"
        then
            text:SetText(
                self:T("CRAFT_DB_EMPTY", "The WoW profession database did not return equipment recipes.")
            )
        else
            text:SetText(
                self:T("CRAFT_NO_MATCH", "The shared craft database is loaded, but no items match the selected SLOT and EQUIPMENT TYPE filters.")
                .. " " .. self:T("CRAFT_SHOW_ALL", "Choose ALL SLOTS / ALL TYPES to view the full shared catalogue.")
            )
        end

        text:SetTextColor(
            unpack(
                self.COLORS.muted
            )
        )

        local databaseStatus =
            panel:CreateFontString(
                nil,
                "OVERLAY"
            )

        databaseStatus:SetFontObject(
            GameFontNormalSmall
        )

        databaseStatus:SetPoint(
            "TOPRIGHT",
            panel,
            "TOPRIGHT",
            -14,
            -18
        )

        databaseStatus:SetText(
            "CRAFT DB: SHARED "
            .. tostring(Crafting:GetBundledRecipeCount())
            .. "  +  CLIENT "
            .. tostring(Crafting:GetCachedRecipeCount())
        )

        databaseStatus:SetTextColor(
            unpack(
                self.COLORS.gold
            )
        )

        content:SetHeight(
            140
        )

        return
    end

    local databaseStatus =
        content:CreateFontString(
            nil,
            "OVERLAY"
        )

    databaseStatus:SetFontObject(
        GameFontNormalSmall
    )

    databaseStatus:SetPoint(
        "TOPRIGHT",
        content,
        "TOPRIGHT",
        -12,
        0
    )

    databaseStatus:SetText(
        "CRAFT DB: SHARED "
        .. tostring(Crafting:GetBundledRecipeCount())
        .. "  +  CLIENT "
        .. tostring(Crafting:GetCachedRecipeCount())
    )

    databaseStatus:SetTextColor(
        unpack(
            self.COLORS.muted
        )
    )

    local grouped = {}

    for _, option in ipairs(
        options
    ) do
        local slotID =
            tonumber(
                option.slotID
            )
            or 14

        grouped[slotID] =
            grouped[slotID]
            or {}

        table.insert(
            grouped[slotID],
            option
        )
    end

    local y = -22

    for _, slotID in ipairs(
        Data.SLOT_ORDER
    ) do
        local slotOptions =
            grouped[slotID]

        if slotOptions
            and #slotOptions > 0
        then
            local header =
                CreatePanel(
                    content
                )

            header:SetSize(
                1060,
                34
            )

            header:SetPoint(
                "TOPLEFT",
                content,
                "TOPLEFT",
                0,
                y
            )

            local headerText =
                header:CreateFontString(
                    nil,
                    "OVERLAY"
                )

            headerText:SetFontObject(
                GameFontNormalLarge
            )

            headerText:SetPoint(
                "LEFT",
                header,
                "LEFT",
                10,
                0
            )

            headerText:SetText(
                Data.SLOT_NAMES[
                    slotID
                ]
                or "OTHER"
            )

            headerText:SetTextColor(
                unpack(
                    self.COLORS.gold
                )
            )

            y = y - 40

            for _, option in ipairs(
                slotOptions
            ) do
                local row =
                    CreatePanel(
                        content
                    )

                row:SetSize(
                    math.max(760, (content:GetWidth() or 1060) - 4),
                    self:Metric(58, 54, 86)
                )

                row:SetPoint(
                    "TOPLEFT",
                    content,
                    "TOPLEFT",
                    0,
                    y
                )

                local itemInfo =
                    Query:GetItemInfo(
                        option.itemID
                    )

                local icon =
                    row:CreateTexture(
                        nil,
                        "ARTWORK"
                    )

                icon:SetSize(
                    self:Metric(38, 34, 54),
                    self:Metric(38, 34, 54)
                )

                icon:SetPoint(
                    "LEFT",
                    row,
                    "LEFT",
                    10,
                    0
                )

                icon:SetTexture(
                    itemInfo.icon
                )

                icon:SetTexCoord(
                    0.08,
                    0.92,
                    0.08,
                    0.92
                )

                local name =
                    row:CreateFontString(
                        nil,
                        "OVERLAY"
                    )

                name:SetFontObject(
                    GameFontNormal
                )

                name:SetPoint(
                    "TOPLEFT",
                    icon,
                    "TOPRIGHT",
                    10,
                    -2
                )

                name:SetPoint(
                    "RIGHT",
                    row,
                    "RIGHT",
                    -170,
                    0
                )

                name:SetHeight(
                    self:Metric(20, 18, 34)
                )

                name:SetJustifyH(
                    "LEFT"
                )

                name:SetWordWrap(
                    false
                )

                local localizedName =
                    itemInfo.name
                    or option.itemName
                    or (
                        "ITEM "
                        .. tostring(
                            option.itemID
                        )
                    )

                name:SetText(
                    Query:GetItemDisplayName(
                        option.itemID,
                        localizedName
                    )
                )

                local meta =
                    row:CreateFontString(
                        nil,
                        "OVERLAY"
                    )

                meta:SetFontObject(
                    GameFontNormalSmall
                )

                meta:SetPoint(
                    "BOTTOMLEFT",
                    icon,
                    "BOTTOMRIGHT",
                    10,
                    2
                )

                meta:SetPoint(
                    "RIGHT",
                    row,
                    "RIGHT",
                    -170,
                    0
                )

                meta:SetHeight(
                    self:Metric(18, 16, 30)
                )

                meta:SetJustifyH(
                    "LEFT"
                )

                meta:SetWordWrap(
                    false
                )

                meta:SetText(
                    SafeText(
                        option.professionName,
                        "PROFESSION"
                    )
                    .. " | ilvl "
                    .. SafeText(
                        option.iLvlMin,
                        "?"
                    )
                    .. "-"
                    .. SafeText(
                        option.iLvlMax,
                        option.iLvlMin
                        or "?"
                    )
                )

                meta:SetTextColor(
                    unpack(
                        self.COLORS.gold
                    )
                )

                local addButton =
                    CreateFrame(
                        "Button",
                        nil,
                        row,
                        "UIPanelButtonTemplate"
                    )

                addButton:SetSize(
                    self:Metric(138, 120, 190),
                    self:Metric(30, 28, 42)
                )

                addButton:SetPoint(
                    "RIGHT",
                    row,
                    "RIGHT",
                    -12,
                    0
                )

                local tracked =
                    self:GetLootTrackedState(
                        option.itemID
                    )

                addButton:SetText(
                    tracked
                    and self:T("PRIORITY", "PRIORITY")
                    or self:T("ADD_TO_MY_LOOT", "ADD TO MY LOOT")
                )

                addButton:SetScript(
                    "OnClick",
                    function()
                        self:OpenLootPriorityMenu(
                            addButton,
                            option.itemID,
                            {
                                sourceType = "CRAFTED",
                                sourceID = option.professionID,
                                name = option.professionName,
                                slotID = option.slotID,
                                professionID = option.professionID,
                                professionName = option.professionName,
                            },
                            nil,
                            {
                                type = "CRAFTED",
                                key = tostring(option.professionID or ""),
                                rank = 1,
                                entry = {
                                    ilvl = option.iLvlMax or option.iLvlMin,
                                    groupLabel = "CRAFTED",
                                    label = tostring(option.iLvlMax or option.iLvlMin or ""),
                                },
                            }
                        )
                    end
                )

                row:SetScript(
                    "OnEnter",
                    function()

                        GameTooltip:SetOwner(
                            row,
                            "ANCHOR_RIGHT"
                        )

                        GameTooltip:ClearLines()

                        local previewEntry = nil
                        local previewIlvl = tonumber(option.iLvlMax or option.iLvlMin)
                        if previewIlvl then
                            previewEntry = {
                                ilvl = previewIlvl,
                                groupLabel = "CRAFTED",
                                label = tostring(previewIlvl),
                            }
                        end

                        local hyperlink = nil
                        if Upgrade and Upgrade.BuildPreviewItemLink then
                            hyperlink = Upgrade:BuildPreviewItemLink(
                                option.itemID,
                                UI.LootSpecID,
                                previewEntry
                            )
                        end

                        if not hyperlink then
                            hyperlink = C_Item
                                and C_Item.GetItemInfo
                                and select(
                                    2,
                                    C_Item.GetItemInfo(
                                        option.itemID
                                    )
                                )
                        end

                        GameTooltip:SetHyperlink(
                            hyperlink
                            or (
                                "item:"
                                .. tostring(
                                    option.itemID
                                )
                            )
                        )

                        GameTooltip:Show()

                    end
                )

                row:SetScript(
                    "OnLeave",
                    ClearTooltip
                )

                y = y - 64
            end

            y = y - 10
        end
    end

    content:SetHeight(
        math.max(
            math.abs(y) + 20,
            100
        )
    )
end

------------------------------------------------------------
-- WINDOW CREATION
------------------------------------------------------------

