local _, ns = ...

------------------------------------------------------------
-- Constants
------------------------------------------------------------
local EQUIP_PANEL_WIDTH = 440
local INFO_PANEL_WIDTH = 280
local FRAME_HEIGHT = 500
local SLOT_SIZE = 36
local LABEL_MAX_WIDTH = 150

local QUALITY_COLORS = {
    [0] = { 0.6, 0.6, 0.6 },   -- Poor
    [1] = { 1.0, 1.0, 1.0 },   -- Common
    [2] = { 0.12, 1.0, 0.0 },  -- Uncommon
    [3] = { 0.0, 0.44, 0.87 }, -- Rare
    [4] = { 0.64, 0.21, 0.93 },-- Epic
    [5] = { 1.0, 0.5, 0.0 },   -- Legendary
}

------------------------------------------------------------
-- Main container (holds both panels)
------------------------------------------------------------
local container = CreateFrame("Frame", "YippYappHelperFrame", UIParent)
container:SetSize(EQUIP_PANEL_WIDTH + INFO_PANEL_WIDTH, FRAME_HEIGHT)
container:SetPoint("CENTER")
container:SetMovable(true)
container:EnableMouse(true)
container:RegisterForDrag("LeftButton")
container:SetScript("OnDragStart", function(self)
    if not ns.upgradeVendorOpen then
        self:StartMoving()
    end
end)
container:SetScript("OnDragStop", container.StopMovingOrSizing)
container:SetClampedToScreen(true)
container:SetFrameStrata("HIGH")
container:Hide()
ns.MainFrame = container

-- ESC closes the frame: add/remove from UISpecialFrames dynamically
-- so we don't eat ESC when the frame is hidden
container:SetScript("OnShow", function()
    tinsert(UISpecialFrames, "YippYappHelperFrame")
end)
container:SetScript("OnHide", function()
    for i = #UISpecialFrames, 1, -1 do
        if UISpecialFrames[i] == "YippYappHelperFrame" then
            table.remove(UISpecialFrames, i)
            break
        end
    end
end)

------------------------------------------------------------
-- Left panel: Equipment
------------------------------------------------------------
local equipPanel = CreateFrame("Frame", nil, container, "BackdropTemplate")
equipPanel:SetSize(EQUIP_PANEL_WIDTH, FRAME_HEIGHT)
equipPanel:SetPoint("TOPLEFT")
equipPanel:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    edgeSize = 16,
    insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
equipPanel:SetBackdropColor(0.08, 0.08, 0.08, 0.92)
equipPanel:SetBackdropBorderColor(0.6, 0.6, 0.6, 1)

-- Title
local equipTitle = equipPanel:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
equipTitle:SetPoint("TOP", 0, -12)
equipTitle:SetText("|cff00ff00YippYapp Helper|r")

-- Close button
local close = CreateFrame("Button", nil, container, "UIPanelCloseButton")
close:SetPoint("TOPRIGHT", container, "TOPRIGHT", -2, -2)

-- Divider below title
local equipDivider = equipPanel:CreateTexture(nil, "ARTWORK")
equipDivider:SetHeight(1)
equipDivider:SetPoint("TOPLEFT", 12, -36)
equipDivider:SetPoint("TOPRIGHT", -12, -36)
equipDivider:SetColorTexture(0.5, 0.5, 0.5, 0.6)

------------------------------------------------------------
-- Right panel: Crests & Suggestions
------------------------------------------------------------
local infoPanel = CreateFrame("Frame", nil, container, "BackdropTemplate")
infoPanel:SetSize(INFO_PANEL_WIDTH, FRAME_HEIGHT)
infoPanel:SetPoint("TOPLEFT", equipPanel, "TOPRIGHT", -1, 0)
infoPanel:SetBackdrop({
    bgFile = "Interface\\Buttons\\WHITE8x8",
    edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
    edgeSize = 16,
    insets = { left = 4, right = 4, top = 4, bottom = 4 },
})
infoPanel:SetBackdropColor(0.08, 0.08, 0.08, 0.92)
infoPanel:SetBackdropBorderColor(0.6, 0.6, 0.6, 1)

-- Crests header
local crestHeader = infoPanel:CreateFontString(nil, "OVERLAY", "GameFontNormal")
crestHeader:SetPoint("TOPLEFT", 14, -14)
crestHeader:SetText("Crests")

local crestDivider = infoPanel:CreateTexture(nil, "ARTWORK")
crestDivider:SetHeight(1)
crestDivider:SetPoint("TOPLEFT", crestHeader, "BOTTOMLEFT", 0, -4)
crestDivider:SetPoint("RIGHT", infoPanel, "RIGHT", -14, 0)
crestDivider:SetColorTexture(0.5, 0.5, 0.5, 0.4)

-- Crest rows (5 for Midnight S1)
ns.CrestFrames = {}
for i = 1, #ns.CRESTS do
    local row = CreateFrame("Frame", nil, infoPanel)
    row:SetSize(INFO_PANEL_WIDTH - 28, 20)
    row:SetPoint("TOPLEFT", crestDivider, "BOTTOMLEFT", 0, -4 - (i - 1) * 22)

    row.icon = row:CreateTexture(nil, "ARTWORK")
    row.icon:SetSize(16, 16)
    row.icon:SetPoint("LEFT")

    row.text = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    row.text:SetPoint("LEFT", row.icon, "RIGHT", 6, 0)
    row.text:SetJustifyH("LEFT")

    ns.CrestFrames[i] = row
end

-- Suggestions header
local suggestHeader = infoPanel:CreateFontString(nil, "OVERLAY", "GameFontNormal")
suggestHeader:SetPoint("TOPLEFT", crestDivider, "BOTTOMLEFT", 0, -4 - (#ns.CRESTS) * 22 - 10)
suggestHeader:SetText("Suggestions")

local suggestDivider = infoPanel:CreateTexture(nil, "ARTWORK")
suggestDivider:SetHeight(1)
suggestDivider:SetPoint("TOPLEFT", suggestHeader, "BOTTOMLEFT", 0, -4)
suggestDivider:SetPoint("RIGHT", infoPanel, "RIGHT", -14, 0)
suggestDivider:SetColorTexture(0.5, 0.5, 0.5, 0.4)

-- Scrollable suggestions area
local suggestScroll = CreateFrame("ScrollFrame", nil, infoPanel, "UIPanelScrollFrameTemplate")
suggestScroll:SetPoint("TOPLEFT", suggestDivider, "BOTTOMLEFT", 0, -6)
suggestScroll:SetPoint("BOTTOMRIGHT", infoPanel, "BOTTOMRIGHT", -28, 12)

local suggestContent = CreateFrame("Frame", nil, suggestScroll)
suggestContent:SetSize(INFO_PANEL_WIDTH - 42, 1)
suggestScroll:SetScrollChild(suggestContent)

ns.SuggestContent = suggestContent
ns.SuggestEntries = {}
local suggestFontPool = {}
local suggestFontPoolIdx = 0

local function AcquireFontString(template)
    suggestFontPoolIdx = suggestFontPoolIdx + 1
    local fs = suggestFontPool[suggestFontPoolIdx]
    if not fs then
        fs = suggestContent:CreateFontString(nil, "OVERLAY", template or "GameFontNormalSmall")
        suggestFontPool[suggestFontPoolIdx] = fs
    else
        fs:SetFontObject(template or "GameFontNormalSmall")
        fs:SetTextColor(1, 1, 1)
        fs:SetWordWrap(false)
    end
    fs:ClearAllPoints()
    fs:Show()
    return fs
end

function ns:RefreshSuggestions()
    -- Hide all previously used font strings and reset pool index
    for i = 1, suggestFontPoolIdx do
        suggestFontPool[i]:Hide()
    end
    suggestFontPoolIdx = 0
    wipe(ns.SuggestEntries)

    local recommendations = ns:GetAllRecommendations()
    local yOffset = 0

    -- Sort: actionable items first (Upgrade now, then others), skip empty/maxed
    local sorted = {}
    for _, slotInfo in ipairs(ns.SLOT_IDS) do
        local r = recommendations[slotInfo.slot]
        if r and r.recommendation ~= ns.RECOMMEND.NO_ITEM and r.recommendation ~= ns.RECOMMEND.MAXED then
            table.insert(sorted, r)
        end
    end

    -- Sort by: recommendation priority, then slot priority (high value first)
    local labelOrder = {
        [ns.RECOMMEND.UPGRADE_NOW]    = 1,
        [ns.RECOMMEND.BAD_INVESTMENT] = 2,
        [ns.RECOMMEND.HOLD_CRESTS]    = 3,
        [ns.RECOMMEND.SAFE_TEMP]      = 4,
        [ns.RECOMMEND.UPGRADE_LATER]  = 5,
        [ns.RECOMMEND.CRAFT_INSTEAD]  = 6,
        [ns.RECOMMEND.WAIT_BETTER]    = 7,
    }
    table.sort(sorted, function(a, b)
        local oa = labelOrder[a.recommendation] or 99
        local ob = labelOrder[b.recommendation] or 99
        if oa ~= ob then return oa < ob end
        local pa = ns.SLOT_PRIORITY[a.slotID] or 2
        local pb = ns.SLOT_PRIORITY[b.slotID] or 2
        return pa > pb
    end)

    -- Group by recommendation label
    local lastLabel = nil
    for i, r in ipairs(sorted) do
        local rec = r.recommendation

        if rec.label ~= lastLabel then
            if lastLabel then yOffset = yOffset + 4 end
            local sectionHeader = AcquireFontString("GameFontNormal")
            sectionHeader:SetPoint("TOPLEFT", 0, -yOffset)
            sectionHeader:SetWidth(INFO_PANEL_WIDTH - 42)
            sectionHeader:SetJustifyH("LEFT")
            sectionHeader:SetText("|c" .. rec.color .. rec.label .. "|r")
            table.insert(ns.SuggestEntries, sectionHeader)
            yOffset = yOffset + sectionHeader:GetStringHeight() + 3
            lastLabel = rec.label
        end

        local slotPri = ns.SLOT_PRIORITY[r.slotID] or 2
        local priStr = ""
        if slotPri >= 5 then priStr = "|cff00ff00[!!!]|r "
        elseif slotPri >= 4 then priStr = "|cff88ff88[!!]|r "
        elseif slotPri >= 3 then priStr = "|cffffff88[!]|r "
        end

        local header = AcquireFontString()
        header:SetPoint("TOPLEFT", 4, -yOffset)
        header:SetWidth(INFO_PANEL_WIDTH - 46)
        header:SetJustifyH("LEFT")
        header:SetText(priStr .. "|cffffffff" .. r.slotName .. "|r")
        table.insert(ns.SuggestEntries, header)
        yOffset = yOffset + header:GetStringHeight() + 1

        if r.reason and r.reason ~= "" then
            local reason = AcquireFontString()
            reason:SetPoint("TOPLEFT", 12, -yOffset)
            reason:SetWidth(INFO_PANEL_WIDTH - 54)
            reason:SetJustifyH("LEFT")
            reason:SetWordWrap(true)
            reason:SetTextColor(0.6, 0.6, 0.6)
            reason:SetText(r.reason)
            table.insert(ns.SuggestEntries, reason)
            yOffset = yOffset + reason:GetStringHeight() + 4
        end
    end

    if #sorted == 0 then
        local noItems = AcquireFontString()
        noItems:SetPoint("TOPLEFT", 0, 0)
        noItems:SetTextColor(0.5, 0.5, 0.5)
        noItems:SetText("No upgradeable items found.")
        table.insert(ns.SuggestEntries, noItems)
        yOffset = 20
    end

    suggestContent:SetHeight(math.max(yOffset, 1))
end

------------------------------------------------------------
-- Equipment Slot Buttons
------------------------------------------------------------
ns.SlotButtons = {}

local function CreateSlotButton(parent, slotInfo)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetSize(SLOT_SIZE, SLOT_SIZE)
    btn:SetPoint(slotInfo.anchor, parent, slotInfo.anchor, slotInfo.x, slotInfo.y)

    -- Background
    btn.bg = btn:CreateTexture(nil, "BACKGROUND")
    btn.bg:SetAllPoints()
    btn.bg:SetColorTexture(0.1, 0.1, 0.1, 1)

    -- Icon
    btn.icon = btn:CreateTexture(nil, "ARTWORK")
    btn.icon:SetPoint("TOPLEFT", 1, -1)
    btn.icon:SetPoint("BOTTOMRIGHT", -1, 1)
    btn.icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)

    -- Border: 4 thin edge textures
    local borderThickness = 2
    btn.borderTop = btn:CreateTexture(nil, "OVERLAY")
    btn.borderTop:SetHeight(borderThickness)
    btn.borderTop:SetPoint("TOPLEFT", -1, 1)
    btn.borderTop:SetPoint("TOPRIGHT", 1, 1)

    btn.borderBottom = btn:CreateTexture(nil, "OVERLAY")
    btn.borderBottom:SetHeight(borderThickness)
    btn.borderBottom:SetPoint("BOTTOMLEFT", -1, -1)
    btn.borderBottom:SetPoint("BOTTOMRIGHT", 1, -1)

    btn.borderLeft = btn:CreateTexture(nil, "OVERLAY")
    btn.borderLeft:SetWidth(borderThickness)
    btn.borderLeft:SetPoint("TOPLEFT", -1, 1)
    btn.borderLeft:SetPoint("BOTTOMLEFT", -1, -1)

    btn.borderRight = btn:CreateTexture(nil, "OVERLAY")
    btn.borderRight:SetWidth(borderThickness)
    btn.borderRight:SetPoint("TOPRIGHT", 1, 1)
    btn.borderRight:SetPoint("BOTTOMRIGHT", 1, -1)

    function btn:SetBorderColor(r, g, b, a)
        self.borderTop:SetColorTexture(r, g, b, a)
        self.borderBottom:SetColorTexture(r, g, b, a)
        self.borderLeft:SetColorTexture(r, g, b, a)
        self.borderRight:SetColorTexture(r, g, b, a)
    end
    btn:SetBorderColor(0.5, 0.5, 0.5, 0.8)

    -- Upgrade glow (action bar proc style)
    btn.glowFrame = CreateFrame("Frame", nil, btn)
    btn.glowFrame:SetPoint("TOPLEFT", -8, 8)
    btn.glowFrame:SetPoint("BOTTOMRIGHT", 8, -8)
    btn.glowFrame:SetFrameLevel(btn:GetFrameLevel() - 1)
    btn.glowFrame:Hide()

    btn.glowFrame.ants = btn.glowFrame:CreateTexture(nil, "ARTWORK")
    btn.glowFrame.ants:SetAllPoints()
    btn.glowFrame.ants:SetAtlas("ActionBarSpellHighlightBorder")
    btn.glowFrame.ants:SetVertexColor(1.0, 0.85, 0.0, 0.9)

    btn.glowFrame.animGroup = btn.glowFrame.ants:CreateAnimationGroup()
    btn.glowFrame.animGroup:SetLooping("BOUNCE")
    local fade = btn.glowFrame.animGroup:CreateAnimation("Alpha")
    fade:SetFromAlpha(0.5)
    fade:SetToAlpha(1.0)
    fade:SetDuration(0.6)
    fade:SetSmoothing("IN_OUT")

    -- Upgrade arrow indicator
    btn.upgradeIcon = btn:CreateTexture(nil, "OVERLAY", nil, 7)
    btn.upgradeIcon:SetSize(18, 18)
    btn.upgradeIcon:SetPoint("TOPRIGHT", 4, 4)
    btn.upgradeIcon:SetAtlas("bags-greenarrow")
    btn.upgradeIcon:Hide()

    -- Slot name label (next to icon)
    btn.nameLabel = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    btn.nameLabel:SetTextColor(0.8, 0.8, 0.8)
    btn.nameLabel:SetWidth(LABEL_MAX_WIDTH)
    btn.nameLabel:SetWordWrap(false)

    -- Item level text (below slot name)
    btn.ilvlText = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    btn.ilvlText:SetTextColor(1, 1, 1)
    btn.ilvlText:SetWidth(LABEL_MAX_WIDTH)
    btn.ilvlText:SetWordWrap(false)

    -- Status label (upgrade recommendation)
    btn.statusLabel = btn:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
    btn.statusLabel:SetWidth(LABEL_MAX_WIDTH)
    btn.statusLabel:SetWordWrap(false)

    if slotInfo.anchor == "TOPLEFT" then
        btn.nameLabel:SetJustifyH("LEFT")
        btn.ilvlText:SetJustifyH("LEFT")
        btn.statusLabel:SetJustifyH("LEFT")
        btn.nameLabel:SetPoint("TOPLEFT", btn, "TOPRIGHT", 6, 0)
        btn.ilvlText:SetPoint("TOPLEFT", btn.nameLabel, "BOTTOMLEFT", 0, -1)
        btn.statusLabel:SetPoint("TOPLEFT", btn.ilvlText, "BOTTOMLEFT", 0, -1)
    elseif slotInfo.anchor == "TOPRIGHT" then
        btn.nameLabel:SetJustifyH("RIGHT")
        btn.ilvlText:SetJustifyH("RIGHT")
        btn.statusLabel:SetJustifyH("RIGHT")
        btn.nameLabel:SetPoint("TOPRIGHT", btn, "TOPLEFT", -6, 0)
        btn.ilvlText:SetPoint("TOPRIGHT", btn.nameLabel, "BOTTOMRIGHT", 0, -1)
        btn.statusLabel:SetPoint("TOPRIGHT", btn.ilvlText, "BOTTOMRIGHT", 0, -1)
    elseif slotInfo.anchor == "BOTTOMLEFT" then
        btn.nameLabel:SetJustifyH("LEFT")
        btn.ilvlText:SetJustifyH("LEFT")
        btn.statusLabel:SetJustifyH("LEFT")
        btn.nameLabel:SetPoint("TOPLEFT", btn, "TOPRIGHT", 6, 0)
        btn.ilvlText:SetPoint("TOPLEFT", btn.nameLabel, "BOTTOMLEFT", 0, -1)
        btn.statusLabel:SetPoint("TOPLEFT", btn.ilvlText, "BOTTOMLEFT", 0, -1)
    elseif slotInfo.anchor == "BOTTOMRIGHT" then
        btn.nameLabel:SetJustifyH("RIGHT")
        btn.ilvlText:SetJustifyH("RIGHT")
        btn.statusLabel:SetJustifyH("RIGHT")
        btn.nameLabel:SetPoint("TOPRIGHT", btn, "TOPLEFT", -6, 0)
        btn.ilvlText:SetPoint("TOPRIGHT", btn.nameLabel, "BOTTOMRIGHT", 0, -1)
        btn.statusLabel:SetPoint("TOPRIGHT", btn.ilvlText, "BOTTOMRIGHT", 0, -1)
    end

    -- Tooltip on hover
    btn:SetScript("OnEnter", function(self)
        if self.itemLink then
            GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
            GameTooltip:SetHyperlink(self.itemLink)
            GameTooltip:Show()
        end
    end)
    btn:SetScript("OnLeave", GameTooltip_Hide)

    -- Click to send item to upgrade window
    btn:SetScript("OnClick", function(self, button)
        if button == "LeftButton" and self.slotID then
            if ns.upgradeVendorOpen then
                ns:SendItemToUpgrade(self.slotID)
            else
                print("|cff00ff00YippYapp Helper|r: Open the upgrade vendor to upgrade items.")
            end
        end
    end)
    btn:RegisterForClicks("LeftButtonUp")

    -- Highlight on hover
    btn.highlight = btn:CreateTexture(nil, "HIGHLIGHT")
    btn.highlight:SetAllPoints(btn.icon)
    btn.highlight:SetColorTexture(1, 1, 1, 0.15)

    btn.slotID = slotInfo.slot
    btn.slotName = slotInfo.name
    return btn
end

for _, slotInfo in ipairs(ns.SLOT_IDS) do
    local btn = CreateSlotButton(equipPanel, slotInfo)
    ns.SlotButtons[slotInfo.slot] = btn
end

------------------------------------------------------------
-- Refresh equipped gear display
------------------------------------------------------------
-- Track name colors for display
local TRACK_COLORS = {
    Adventurer = "ff1eff00",
    Veteran    = "ff0070dd",
    Champion   = "ffa335ee",
    Hero       = "ffff8000",
    Myth       = "ffff0000",
}

function ns:RefreshAllSlots()
    for _, slotInfo in ipairs(ns.SLOT_IDS) do
        local btn = ns.SlotButtons[slotInfo.slot]
        local info = ns:GetSlotInfo(slotInfo.slot)

        if info then
            btn.icon:SetTexture(info.icon)
            btn.itemLink = info.link

            -- Color border by quality
            local c = QUALITY_COLORS[info.quality] or QUALITY_COLORS[1]
            btn:SetBorderColor(c[1], c[2], c[3], 0.9)

            -- Get track and upgrade info from ilvl
            local canUpgrade, upgradeInfo = ns:CanUpgradeItem(slotInfo.slot)
            local track = upgradeInfo and upgradeInfo.track or ns:GetTrackFromIlvl(info.ilvl)
            local trackColor = track and TRACK_COLORS[track] or "ffffffff"

            -- Slot name with track label: "Head — Champion 3/5"
            if upgradeInfo and track then
                btn.nameLabel:SetText(slotInfo.name .. " — |c" .. trackColor .. track .. " " .. upgradeInfo.currUpgrade .. "/" .. upgradeInfo.maxUpgrade .. "|r")
            elseif track then
                btn.nameLabel:SetText(slotInfo.name .. " — |c" .. trackColor .. track .. "|r")
            else
                btn.nameLabel:SetText(slotInfo.name)
            end

            -- Get recommendation
            local rec, reason = ns:GetRecommendation(slotInfo.slot)

            if canUpgrade and upgradeInfo then
                -- Show ilvl range: "220 -> 233"
                btn.ilvlText:SetText(info.ilvl .. " -> " .. upgradeInfo.maxIlvl)
                btn.upgradeIcon:Show()
                btn.statusLabel:SetText("|c" .. rec.color .. rec.label .. "|r")
                btn.statusLabel:Show()

                -- Glow for upgradeable items
                btn.glowFrame:Show()
                if not btn.glowFrame.animGroup:IsPlaying() then
                    btn.glowFrame.animGroup:Play()
                end

                -- Color glow based on recommendation
                if rec == ns.RECOMMEND.UPGRADE_NOW then
                    btn.glowFrame.ants:SetVertexColor(0.3, 1.0, 0.3, 1.0)
                elseif rec == ns.RECOMMEND.BAD_INVESTMENT then
                    btn.glowFrame.ants:SetVertexColor(1.0, 0.2, 0.2, 0.8)
                elseif rec == ns.RECOMMEND.HOLD_CRESTS then
                    btn.glowFrame.ants:SetVertexColor(1.0, 0.6, 0.0, 0.9)
                else
                    btn.glowFrame.ants:SetVertexColor(1.0, 0.85, 0.0, 0.9)
                end
            elseif upgradeInfo and not canUpgrade then
                btn.ilvlText:SetText(tostring(info.ilvl))
                btn.upgradeIcon:Hide()
                btn.statusLabel:SetText("|c" .. ns.RECOMMEND.MAXED.color .. "Max rank|r")
                btn.statusLabel:Show()
                btn.glowFrame:Hide()
                btn.glowFrame.animGroup:Stop()
            else
                btn.ilvlText:SetText(tostring(info.ilvl))
                btn.upgradeIcon:Hide()
                btn.statusLabel:SetText("")
                btn.statusLabel:Hide()
                btn.glowFrame:Hide()
                btn.glowFrame.animGroup:Stop()
            end
        else
            btn.icon:SetTexture(nil)
            btn.ilvlText:SetText("")
            btn.upgradeIcon:Hide()
            btn.statusLabel:SetText("")
            btn.statusLabel:Hide()
            btn.itemLink = nil
            btn.nameLabel:SetText("|cff555555" .. slotInfo.name .. "|r")
            btn:SetBorderColor(0.2, 0.2, 0.2, 0.5)
            btn.glowFrame:Hide()
            btn.glowFrame.animGroup:Stop()
        end
    end

    ns:RefreshSuggestions()
end
