local _, ns = ...

local ScrollFrames = {}
ns.UIScrollFrames = ScrollFrames

local UIData = ns.UIData or {}
local PREMIUM = UIData.PREMIUM or {}
local THEME = UIData.THEME or {}
local ARROW_UP_TEXTURE = PREMIUM.arrowUp or "Interface\\AddOns\\Vaultloom\\Assets\\arrow_up_small.tga"
local ARROW_DOWN_TEXTURE = PREMIUM.arrowDown or "Interface\\AddOns\\Vaultloom\\Assets\\arrow_down_small.tga"

local function clamp(value, minimum, maximum)
    if value < minimum then
        return minimum
    end

    if value > maximum then
        return maximum
    end

    return value
end

local function createLabel(parent, fontObject, justify)
    local text = parent:CreateFontString(nil, "OVERLAY", fontObject)
    text:SetJustifyH(justify or "LEFT")
    text:SetJustifyV("MIDDLE")
    return text
end

local function setTextureColor(texture, color, alpha)
    if not texture or type(color) ~= "table" then
        return
    end

    texture:SetVertexColor(color[1], color[2], color[3], alpha == nil and 1 or alpha)
end

function ScrollFrames.ClampPosition(scrollFrame, forceTop)
    if not scrollFrame then
        return
    end

    if type(scrollFrame.UpdateScrollChildRect) == "function" then
        scrollFrame:UpdateScrollChildRect()
    end

    local current = type(scrollFrame.GetVerticalScroll) == "function" and (tonumber(scrollFrame:GetVerticalScroll()) or 0) or 0
    local range = type(scrollFrame.GetVerticalScrollRange) == "function" and (tonumber(scrollFrame:GetVerticalScrollRange()) or 0) or 0
    local target = current

    if forceTop then
        target = 0
    else
        target = clamp(current, 0, math.max(0, range))
    end

    if type(scrollFrame.SetVerticalScroll) == "function" then
        scrollFrame:SetVerticalScroll(target)
    end
    if scrollFrame.ScrollBar and type(scrollFrame.ScrollBar.SetValue) == "function" then
        scrollFrame.ScrollBar:SetValue(target)
    end
end

function ScrollFrames.Style(scrollFrame)
    if not scrollFrame then
        return
    end

    local scrollBar = scrollFrame.ScrollBar or _G[(scrollFrame:GetName() or "") .. "ScrollBar"]
    if not scrollBar then
        return
    end

    scrollBar:ClearAllPoints()
    scrollBar:SetPoint("TOPRIGHT", scrollFrame, "TOPRIGHT", 18, -2)
    scrollBar:SetPoint("BOTTOMRIGHT", scrollFrame, "BOTTOMRIGHT", 18, 2)
    scrollBar:SetWidth(18)

    for _, region in ipairs({ scrollBar:GetRegions() }) do
        if region and region:IsObjectType("Texture") then
            region:SetAlpha(0)
        end
    end

    if scrollBar.Track then
        scrollBar.Track:Hide()
    end

    if not scrollBar.track then
        scrollBar.track = CreateFrame("Frame", nil, scrollBar)
        scrollBar.track:SetPoint("TOPLEFT", 3, -18)
        scrollBar.track:SetPoint("BOTTOMRIGHT", -3, 18)

        scrollBar.track.bg = scrollBar.track:CreateTexture(nil, "BACKGROUND")
        scrollBar.track.bg:SetAllPoints()
        scrollBar.track.bg:SetTexture(PREMIUM.scrollTrack)

        scrollBar.track.gloss = scrollBar.track:CreateTexture(nil, "ARTWORK")
        scrollBar.track.gloss:SetPoint("TOPLEFT", 1, -1)
        scrollBar.track.gloss:SetPoint("TOPRIGHT", -1, -1)
        scrollBar.track.gloss:SetHeight(1)
        scrollBar.track.gloss:SetTexture("Interface\\Buttons\\WHITE8X8")
    end

    scrollBar.track.bg:SetVertexColor(1, 1, 1, 0.92)
    scrollBar.track.gloss:SetColorTexture(1, 1, 1, 0.02)

    local thumb = scrollBar.ThumbTexture or scrollBar:GetThumbTexture()
    if thumb then
        thumb:SetTexture(PREMIUM.scrollThumb)
        thumb:SetSize(12, 40)
        thumb:SetVertexColor(1, 1, 1, 0.94)
    end

    local function styleArrowButton(button, direction)
        if not button then
            return
        end

        button:ClearAllPoints()
        if direction == "up" then
            button:SetPoint("TOP", scrollBar, "TOP", 0, 0)
        else
            button:SetPoint("BOTTOM", scrollBar, "BOTTOM", 0, 0)
        end
        button:SetSize(16, 16)

        local normal = button:GetNormalTexture()
        local pushed = button:GetPushedTexture()
        local disabled = button:GetDisabledTexture()
        local highlight = button:GetHighlightTexture()

        if normal then normal:SetAlpha(0) end
        if pushed then pushed:SetAlpha(0) end
        if disabled then disabled:SetAlpha(0) end
        if highlight then highlight:SetAlpha(0) end

        if not button.vlBg then
            button.vlBg = button:CreateTexture(nil, "BACKGROUND")
            button.vlBg:SetAllPoints()
            button.vlBg:SetTexture(PREMIUM.buttonNormal)
        end

        if not button.vlHover then
            button.vlHover = button:CreateTexture(nil, "ARTWORK")
            button.vlHover:SetAllPoints()
            button.vlHover:SetTexture(PREMIUM.buttonHover)
        end

        if not button.vlPressed then
            button.vlPressed = button:CreateTexture(nil, "ARTWORK", nil, 1)
            button.vlPressed:SetAllPoints()
            button.vlPressed:SetTexture(PREMIUM.buttonPressed)
        end

        setTextureColor(button.vlBg, { 1, 1, 1 }, 0.92)
        button.vlHover:SetAlpha(0)
        button.vlPressed:SetAlpha(0)

        if button.vlGlyph and button.vlGlyph.Hide then
            button.vlGlyph:Hide()
        end

        if not button.vlArrowIcon then
            button.vlArrowIcon = button:CreateTexture(nil, "OVERLAY")
        end
        button.vlArrowIcon:SetTexture(direction == "up" and ARROW_UP_TEXTURE or ARROW_DOWN_TEXTURE)
        button.vlArrowIcon:SetSize(12, 12)
        button.vlArrowIcon:ClearAllPoints()
        button.vlArrowIcon:SetPoint("CENTER", 0, 0)
        button.vlArrowIcon:SetVertexColor(1, 1, 1, 0.96)
        button.vlArrowIcon:Show()

        if not button.vlStateHooks then
            button:HookScript("OnEnter", function(self)
                self.vlHover:SetAlpha(1)
            end)

            button:HookScript("OnLeave", function(self)
                self.vlHover:SetAlpha(0)
                self.vlPressed:SetAlpha(0)
            end)

            button:HookScript("OnMouseDown", function(self)
                self.vlHover:SetAlpha(0)
                self.vlPressed:SetAlpha(1)
            end)

            button:HookScript("OnMouseUp", function(self)
                self.vlPressed:SetAlpha(0)
                self.vlHover:SetAlpha(self:IsMouseOver() and 1 or 0)
            end)

            button.vlStateHooks = true
        end
    end

    styleArrowButton(scrollBar.ScrollUpButton or _G[(scrollBar:GetName() or "") .. "ScrollUpButton"], "up")
    styleArrowButton(scrollBar.ScrollDownButton or _G[(scrollBar:GetName() or "") .. "ScrollDownButton"], "down")
end
