local EasyCursorTrails = EasyCursorTrails or {}
_G["EasyCursorTrails"] = EasyCursorTrails



-------------------------
-- Local Variables
-------------------------
local trailPool       = {}
local cursorPositions = {}
local colorIndexTrail     = 0
local pulseValueTrail     = 0.5
local pulseDirectionTrail = 1
local previousCursorX, previousCursorY = nil, nil
local cursorStopped   = false

-- We'll define customCursor at file scope:
local customCursor = nil


-------------------------
-- Local Variables
-------------------------
local trailPool       = {}
local cursorPositions = {}
local colorIndexTrail     = 0
local pulseValueTrail     = 0.5
local pulseDirectionTrail = 1
local previousCursorX, previousCursorY = nil, nil
local cursorStopped   = false

-- We'll define customCursor at file scope:
local customCursor = nil

-------------------------
-- Defaults
-------------------------
local defaults = {
    ["cursorSize"] = 95,
    ["glowIntensity"] = 0.800000011920929,
    ["trailColor"] = {
    ["a"] = 1,
    ["b"] = 1,
    ["g"] = 1,
    ["r"] = 1,
    },
    ["glowHollowness"] = 0,
    ["trailCount"] = 23,
    ["glowBelow"] = false,
    ["glowAboveCursor"] = false,
    ["cursorColor"] = {
    ["a"] = 1,
    ["b"] = 1,
    ["g"] = 0.9960784912109375,
    ["r"] = 0.545098066329956,
    },
    ["glowRadius"] = 0.1195038557052612,
    ["trailFrameStrata"] = "TOOLTIP",
    ["glowColor"] = {
    ["a"] = 1,
    ["b"] = 0.917647123336792,
    ["g"] = 1,
    ["r"] = 0.3568627536296845,
    },
    ["additionalEffects"] = 1,
    ["numGlows"] = 30,
    ["glowPulsingIntensity"] = 0.5,
    ["cursorOffsetX"] = -1,
    ["trailSizeStart"] = 1,
    ["glowThickness"] = 0.800000011920929,
    ["trailColorEffect"] = 11,
    ["pulsingSpeed"] = 10,
    ["trailLayerSpacing"] = 26,
    ["disableGlowPulsing"] = false,
    ["trailMovementEffect"] = 2,
    ["cursorOffsetY"] = 5,
    ["trailOffsetY"] = 1,
    ["trailOffsetX"] = 1,
    ["cursorColorEffect"] = 5,
    ["cursorFrameStrata"] = "BACKGROUND",
    ["selectedCursorTextureName"] = "Circle_1_Hovering",
    ["trailInitialSeparation"] = 48,
    ["cursorTexture"] = 34,
    ["enableTrails"] = true,
    ["trailSizeEnd"] = 44,
    ["minimapPosition"] = {
    ["y"] = 0,
    ["x"] = 0,
    },
    ["trailDelay"] = 0.1,
    ["menuPosition"] = {
    ["y"] = -19.49995803833008,
    ["x"] = -275.8334350585938,
    ["point"] = "TOP",
    ["relativePoint"] = "TOP",
    },
    ["selectedGlowEffect"] = 5,
    ["patternGlowCount"] = 29,
    ["trailLayerCount"] = 9,
    ["trailTexture"] = 1,
    ["glowSize"] = 0.699999988079071,
    }
    
    

-- 2. Initialize Saved Variables with Defaults
if not EasyCursorTrailsDB then
    -- First-time load: Assign all default settings
    EasyCursorTrailsDB = {}
    for key, value in pairs(defaults) do
        if type(value) == "table" then
            EasyCursorTrailsDB[key] = {}
            for subKey, subValue in pairs(value) do
                EasyCursorTrailsDB[key][subKey] = subValue
            end
        else
            EasyCursorTrailsDB[key] = value
        end
    end
else
    -- Subsequent loads: Assign missing settings without overwriting existing ones
    for key, value in pairs(defaults) do
        if EasyCursorTrailsDB[key] == nil then
            if type(value) == "table" then
                EasyCursorTrailsDB[key] = {}
                for subKey, subValue in pairs(value) do
                    EasyCursorTrailsDB[key][subKey] = subValue
                end
            else
                EasyCursorTrailsDB[key] = value
            end
        elseif type(value) == "table" and type(EasyCursorTrailsDB[key]) == "table" then
            -- For nested tables, assign missing sub-keys
            for subKey, subValue in pairs(value) do
                if EasyCursorTrailsDB[key][subKey] == nil then
                    EasyCursorTrailsDB[key][subKey] = subValue
                end
            end
        end
    end
end
-------------------------
-- Custom Cursors
-------------------------
local customCursorTextures = {
    {
        name = "Pearl (Use Custom + Glow Effect)",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Pearl",
        animated = false,
    },
    {
        name = "Alien",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Alien3",
        animated = false,
    },
    {
        name = "Broom Stick",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\BroomStick1",
        animated = false,
    },
    {
        name = "Bullet",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Bullet1",
        animated = false,
    },
    {
        name = "Vibrant Sniper Scope",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\vibrant_sniper_scope",
        animated = false,
    },
    {
        name = "Sniper Scope",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\sniper_scope",
        animated = false,
    },
    {
        name = "Sniper Scope 4",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\sniper_scope4",
        animated = false,
    },
    {
        name = "Dirty Lens",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\dirty_lens",
        animated = false,
    },

    {
        name = "Circle 1",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle1",
        animated = false,
    },
    {
        name = "Circle 2",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle2",
        animated = false,
    },
    {
        name = "Circle 3",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle3",
        animated = false,
    },
    {
        name = "Circle 4",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle4",
        animated = false,
    },
    {
        name = "Circle 5",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle5",
        animated = false,
    },
    {
        name = "Circle_thin_mid",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle_thin_mid",
        animated = false,
    },
    {
        name = "Circle White",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle_White",
        animated = false,
    },
    {
        name = "2 Semi Circle 2",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\2_Semi_Circle_2",
        animated = false,
    },
    {
        name = "2 Semi Circle 5",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\2_Semi_Circle_5",
        animated = false,
    },
    {
        name = "Diamond Left",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Diamond_Left",
        animated = false,
    },
    {
        name = "Diamond Cystal",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Diamond_Crystal",
        animated = false,
    },
    {
        name = "Glass 1",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Glass1",
        animated = false,
    },
    {
        name = "Glass 2",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Glass2",
        animated = false,
    },
    {
        name = "Cursor 1",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\cursor1",
        animated = false,
    },
    {
        name = "Cursor 2",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\cursor2",
        animated = false,
    },
    {
        name = "Golden Ring",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Golden_Ring",
        animated = false,
    },
    {
        name = "Golden Heart",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Golden_Heart",
        animated = false,
    },

    {
        name = "Heart 1",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Heart_White",
        animated = false,
    },
    {
        name = "Heart 2",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Heart3",
        animated = false,
    },
    {
        name = "Heart 3",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Heart5",
        animated = false,
    },
    {
        name = "Heart 4",
        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Heart7",
        animated = false,
    },

    -- Animated Example
    {
        name = "RGB Rotate",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\RGB\\RGB_Rotate_8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.8,
    },
    {
        name = "Yin and Yang v2",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_v8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.6,
    },
    {
        name = "Yin and Yang",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Yin_Yang\\Yin_Yang_8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.6,
    },
    {
        name = "Radar",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Radar\\Radar_8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 2.5,
    },
    {
        name = "Circle",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_1_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_2_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_3_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_4_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_5_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_6_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_7_Hovering.tga",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_8_Hovering.tga",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.5,
    },
    {
        name = "Circle_focus",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\CCircle_focus_4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Circle\\Circle_focus_8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.5,
    },
    {
        name = "Butterfly Hovering",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_1.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_2.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_3.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_4.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_5.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_6.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_7.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Butterfly\\Butterfly_8.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.6,
    },
    {
        name = "Fairy Hovering",
        textures = {
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_1_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_2_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_3_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_4_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_5_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_6_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_7_Hovering.blp",
            "Interface\\AddOns\\EasyCursorTrails\\Textures\\Cursors\\Fairy\\Fairy_Left_8_Hovering.blp",
        },
        animated = true,
        totalFrames = 8,
        animationDuration = 0.3,
    },
}



---------------------------------------------------------------------------
-- dynamicPatterns: shape generation for glows with adjustable positioning
---------------------------------------------------------------------------
EasyCursorTrails.dynamicPatterns = EasyCursorTrails.dynamicPatterns or {}

-- Helper function to generate a single "V" shape
local function generateVShape(rotationAngle, xOffset, yOffset, length, width)
    local points = {}
    
    -- Convert rotation angle from degrees to radians
    local radians = math.rad(rotationAngle or 0)
    
    -- Define the three points of the "V"
    local baseLeft = {
        x = -width,
        y = -0
    }
    local tip = {
        x = 0,
        y = length
    }
    local baseRight = {
        x = width,
        y = 0
    }
    
    -- Function to rotate a point around the origin
    local function rotatePoint(point, radians)
        return {
            x = point.x * math.cos(radians) - point.y * math.sin(radians),
            y = point.x * math.sin(radians) + point.y * math.cos(radians)
        }
    end
    
    -- Rotate points
    local rotatedBaseLeft = rotatePoint(baseLeft, radians)
    local rotatedTip = rotatePoint(tip, radians)
    local rotatedBaseRight = rotatePoint(baseRight, radians)
    
    -- Apply offsets
    rotatedBaseLeft.x = rotatedBaseLeft.x + xOffset
    rotatedBaseLeft.y = rotatedBaseLeft.y + yOffset
    rotatedTip.x = rotatedTip.x + xOffset
    rotatedTip.y = rotatedTip.y + yOffset
    rotatedBaseRight.x = rotatedBaseRight.x + xOffset
    rotatedBaseRight.y = rotatedBaseRight.y + yOffset
    
    -- Insert points into the table
    table.insert(points, rotatedBaseLeft)
    table.insert(points, rotatedTip)
    table.insert(points, rotatedBaseRight)
    
    return points
end



-- 1. Helper function to generate points between two points
local function generateLinePoints(startPoint, endPoint, numPoints)
    local points = {}
    if numPoints < 2 then numPoints = 2 end -- Ensure at least two points
    for i = 0, numPoints - 1 do
        local ratio = i / (numPoints - 1)
        local x = startPoint.x + (endPoint.x - startPoint.x) * ratio
        local y = startPoint.y + (endPoint.y - startPoint.y) * ratio
        table.insert(points, { x = x, y = y })
    end
    return points
end

-- 2. Helper function to generate points for a single "V" shape
local function generateArrowHead(numPoints, direction, rotationAngle, xOffset, yOffset, length, width)
    local points = {}
    
    -- Convert rotation angle from degrees to radians
    local radians = math.rad(rotationAngle or 0)
    
    -- Define the three points of the "V"
    local baseLeft = { x = -width * direction.leftOrRight, y = 0 }
    local tip = { x = 0, y = length * direction.upOrDown }
    local baseRight = { x = width * direction.leftOrRight, y = 0 }
    
    -- Function to rotate a point around the origin and apply offsets
    local function rotatePoint(point, radians)
        return {
            x = point.x * math.cos(radians) - point.y * math.sin(radians) + xOffset,
            y = point.x * math.sin(radians) + point.y * math.cos(radians) + yOffset
        }
    end
    
    -- Rotate points
    local rotatedBaseLeft = rotatePoint(baseLeft, radians)
    local rotatedTip = rotatePoint(tip, radians)
    local rotatedBaseRight = rotatePoint(baseRight, radians)
    
    -- Generate points for left side of "V"
    local leftPoints = generateLinePoints(rotatedBaseLeft, rotatedTip, math.ceil(numPoints / 2))
    
    -- Generate points for right side of "V"
    local rightPoints = generateLinePoints(rotatedTip, rotatedBaseRight, math.floor(numPoints / 2))
    
    -- Combine points
    for _, point in ipairs(leftPoints) do
        table.insert(points, point)
    end
    for _, point in ipairs(rightPoints) do
        table.insert(points, point)
    end
    
    return points
end


-- 2. Helper function to generate points for a single "U" shape
local function generateUShape(numPoints, direction, rotationAngle, xOffset, yOffset, length, width)
    local points = {}
    
    -- Convert rotation angle from degrees to radians
    local radians = math.rad(rotationAngle or 0)
    
    -- Define the key points of the "U"
    local topLeft = { x = -width, y = 0 }
    local bottomLeft = { x = -width, y = -length }
    local bottomRight = { x = width, y = -length }
    local topRight = { x = width, y = 0 }
    
    -- Function to rotate a point around the origin and apply offsets
    local function rotatePoint(point, radians)
        return {
            x = point.x * math.cos(radians) - point.y * math.sin(radians) + xOffset,
            y = point.x * math.sin(radians) + point.y * math.cos(radians) + yOffset
        }
    end
    
    -- Rotate and offset points
    local rotatedTopLeft = rotatePoint(topLeft, radians)
    local rotatedBottomLeft = rotatePoint(bottomLeft, radians)
    local rotatedBottomRight = rotatePoint(bottomRight, radians)
    local rotatedTopRight = rotatePoint(topRight, radians)
    
    -- Allocate points to each segment
    -- Ensure the curved segment has a sufficient number of points for smoothness
    local minCurvePoints = 10
    local curvePoints = math.max(minCurvePoints, math.floor(numPoints * 0.6))
    local remainingPoints = numPoints - curvePoints
    local pointsPerVertical = math.floor(remainingPoints / 2)
    
    -- Ensure pointsPerVertical is at least 2 for smooth vertical lines
    pointsPerVertical = math.max(2, pointsPerVertical)
    
    -- Generate points for left vertical line
    local leftPoints = generateLinePoints(rotatedTopLeft, rotatedBottomLeft, pointsPerVertical)
    
    -- Generate points for the bottom curve (semi-circle)
    local curvePointsList = {}
    for i = 0, curvePoints - 1 do
        local angle = math.pi + (i / (curvePoints - 1)) * math.pi -- from pi to 2pi
        local x = width * math.cos(angle)
        local y = -length * math.sin(angle)
        local rotatedX = x * math.cos(radians) - y * math.sin(radians) + xOffset
        local rotatedY = x * math.sin(radians) + y * math.cos(radians) + yOffset
        table.insert(curvePointsList, {x = rotatedX, y = rotatedY})
    end
    
    -- Generate points for right vertical line
    local rightPoints = generateLinePoints(rotatedBottomRight, rotatedTopRight, pointsPerVertical)
    
    -- Combine all points
    for _, point in ipairs(leftPoints) do
        table.insert(points, point)
    end
    for _, point in ipairs(curvePointsList) do
        table.insert(points, point)
    end
    for _, point in ipairs(rightPoints) do
        table.insert(points, point)
    end
    

    return points
end



-- 2. Helper function to generate points along an ellipse
local function generateEllipsePoints(a, b, numPoints, rotationAngle, xOffset, yOffset)
    local points = {}
    local radians = math.rad(rotationAngle or 0) -- Convert rotation angle to radians
    
    for i = 0, numPoints - 1 do
        local t = (i / numPoints) * 2 * math.pi
        local x = a * math.cos(t)
        local y = b * math.sin(t)
        
        -- Apply rotation
        local rotatedX = x * math.cos(radians) - y * math.sin(radians)
        local rotatedY = x * math.sin(radians) + y * math.cos(radians)
        
        -- Apply offsets
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset
        
        table.insert(points, {x = rotatedX, y = rotatedY})
    end
    

    return points
end

-- 3. Oval Pattern Function
EasyCursorTrails.dynamicPatterns.OvalPattern = function(N)
    local points = {}
    
    -- Define parameters
    local a = 35 -- Horizontal radius; adjust for wider or narrower oval
    local b = 20 -- Vertical radius; adjust for taller or shorter oval
    local rotationAngle = 0 -- Degrees; rotate the oval if desired
    local xOffset = 0 -- Center the oval horizontally
    local yOffset = 0 -- Center the oval vertically
    
    -- Generate points along the ellipse
    points = generateEllipsePoints(a, b, N, rotationAngle, xOffset, yOffset)
    
    return points
end


    -- Helper function to determine the sign of a number
    local function sign(x)
        if x > 0 then
            return 1
        elseif x < 0 then
            return -1
        else
            return 0
        end
    end
    
EasyCursorTrails.dynamicPatterns = {
    -- Circle Pattern
    Circle_White = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the circle)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 0    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            local x = math.cos(angle) * 20 + xOffset
            local y = math.sin(angle) * 20 + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,

    -- Heart Pattern
    Heart_1 = function(N)
        local points = {}
        local tStep = (2 * math.pi) / N
        local scale = 0.7

        -- Position Offsets (Adjust these to move the heart)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 1   -- Vertical offset (e.g., moving the heart up)

        for i = 1, N do
            local t = (i - 1) * tStep
            local x = scale * (16 * math.sin(t)^3) + xOffset
            local y = scale * (
                12 * math.cos(t)
                - 5 * math.cos(2 * t)
                - 2 * math.cos(3 * t)
                - math.cos(4 * t)
            ) + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,

    -- Star Cursor Pattern
    Star_Cursor = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the star)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 0    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            local radius = (i % 2 == 1) and 30 or 15
            local x = math.cos(angle) * radius + xOffset
            local y = math.sin(angle) * radius + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,



    -- Yin and Yang Pattern
    Yin_Yang_Pattern = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the Yin-Yang)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 0    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            -- Simplified circular pattern for Yin and Yang
            local x = math.cos(angle) * 20 + xOffset
            local y = math.sin(angle) * 20 + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,

    -- Butterfly Pattern
    Butterfly_Pattern = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the butterfly)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 0    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            -- Define a butterfly-like pattern with symmetric wings
            local x = math.cos(angle) * (25 + 10 * math.sin(2 * angle)) + xOffset
            local y = math.sin(angle) * (25 + 10 * math.sin(2 * angle)) + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,


    Bullet1 = function(N)
        local points = {}
        
        -- Define parameters
        local FIXED_ROTATION_ANGLE = 42    -- Degrees: Adjust as desired
        local xOffset = 2                 -- Horizontal offset (positive moves right, negative moves left)
        local yOffset = -10                 -- Vertical offset (positive moves up, negative moves down)
        local arrowHeadLength = 20          -- Length of the arrowhead sides
        local arrowHeadWidth = 1         -- Width of the arrowhead base (positive value)
        
        -- Define manual offset parameters for each "U"
        local direction1yoffset = 5         -- Manual Y offset for first "U"
        local direction1xoffset = 2         -- Manual X offset for first "U"
        local direction2yoffset = 2         -- Manual Y offset for second "U"
        local direction2xoffset = 5         -- Manual X offset for second "U"
        
        -- Define direction multipliers for two "U" shapes
        -- First "U" pointing down and to the right
        local direction1 = {
            upOrDown = -1,       -- -1 for "Down", 1 for "Up"
            leftOrRight = 1      -- 1 for "Right", -1 for "Left"
        }
        
        -- Second "U" pointing up and to the left (mirrored)
        local direction2 = {
            upOrDown = 1,        -- 1 for "Up", -1 for "Down"
            leftOrRight = -1     -- -1 for "Left", 1 for "Right"
        }
        
        -- Ensure N is a multiple of 6 for symmetry (since each "U" has three segments)
        if N % 6 ~= 0 then
            N = math.floor(N / 6) * 6
            if N < 6 then
                N = 6
            end
        end
        
        -- Number of points per "U" shape
        local pointsPerU = math.floor(N / 2) -- Each "U" has two curves: left and right
        pointsPerU = math.max(6, pointsPerU) -- At least 6 points per "U" for smoothness
        
        -- Generate first "U" shape (pointing down and to the right) with manual offsets
        local U1Points = generateUShape(
            pointsPerU,
            direction1,
            FIXED_ROTATION_ANGLE,
            xOffset + direction1xoffset,    -- Apply manual X offset
            yOffset + direction1yoffset,    -- Apply manual Y offset
            arrowHeadLength,
            arrowHeadWidth
        )
        
        -- Generate second "U" shape (pointing up and to the left) with manual offsets and rotation
        local U2Points = generateUShape(
            pointsPerU,
            direction2,
            FIXED_ROTATION_ANGLE + 180,   -- Rotate by 180 degrees to mirror
            xOffset + direction2xoffset,    -- Apply manual X offset
            yOffset + direction2yoffset,    -- Apply manual Y offset
            arrowHeadLength,
            arrowHeadWidth
        )
        
        -- Combine points from both "U" shapes to form a diamond
        for _, point in ipairs(U1Points) do
            table.insert(points, point)
        end
        
        for _, point in ipairs(U2Points) do
            table.insert(points, point)
        end
        
        return points
    end,


    -- Cursor (Arrow) Pattern with Fixed Angle, Direction Controls, and Position Offsets
Cursor_Arrow_Pattern = function(N)
    local points = {}
 
    local arrowUpOrDown = 1          -- Positive for "Up", Negative for "Down"
    local arrowLeftOrRight = 1       -- Positive for "Right", Negative for "Left"
  
    local FIXED_ROTATION_ANGLE = 42   -- Adjust this value to rotate the cursor pattern as desired

    local xOffset = 12                -- Horizontal offset (positive moves right, negative moves left)
    local yOffset = -15               -- Vertical offset (positive moves up, negative moves down)

    local shaftLength = 10           -- Increased for visibility
    
    local shaftWidth = 10              -- Currently not directly used but can influence visual spacing
    
    local arrowHeadLength = 30        -- Increase for longer arrowhead sides; decrease for shorter sides
    
    local arrowHeadWidth = 19         -- Increase for a wider arrowhead base; decrease for a narrower base
    
    local verticalMultiplier = sign(arrowUpOrDown)

    local horizontalMultiplier = sign(arrowLeftOrRight)
    
    local radiansOffset = math.rad(FIXED_ROTATION_ANGLE or 45) -- Defaults to 45° if not defined

    local shaftPoints = math.floor(N * 0.6)
    
    local arrowHeadPoints = math.floor((N - shaftPoints) / 2)

    shaftPoints = math.max(1, shaftPoints)
    arrowHeadPoints = math.max(1, arrowHeadPoints)

    for i = 1, shaftPoints do
        -- Calculate the Y-coordinate based on the current point's position along the shaft
        local y = (i / shaftPoints) * shaftLength * verticalMultiplier
        
        -- The X-coordinate remains 0 as the shaft is centered vertically
        local x = 0
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset

        table.insert(points, { x = rotatedX, y = rotatedY })
    end

    for i = 1, arrowHeadPoints do
        -- Calculate the ratio of the current point's position within the arrowhead
        local ratio = i / arrowHeadPoints
        
        -- Calculate the X and Y coordinates for the left side of the arrowhead
        local x = -arrowHeadWidth * (1 - ratio) * horizontalMultiplier
        local y = (shaftLength + arrowHeadLength * ratio) * verticalMultiplier
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset
        
        -- Insert the rotated and offset point into the points table
        table.insert(points, { x = rotatedX, y = rotatedY })
    end
    
 
    for i = 1, arrowHeadPoints do
        -- Calculate the ratio of the current point's position within the arrowhead
        local ratio = i / arrowHeadPoints
        
        -- Calculate the X and Y coordinates for the right side of the arrowhead
        local x = arrowHeadWidth * (1 - ratio) * horizontalMultiplier
        local y = (shaftLength + arrowHeadLength * ratio) * verticalMultiplier
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset
        

        table.insert(points, { x = rotatedX, y = rotatedY })
    end
    

    return points
end,


Diamond = function(N)
    local points = {}
    
    -- Define parameters
    local FIXED_ROTATION_ANGLE = 45    -- Degrees: Adjust as desired
    local xOffset = -10                  -- Horizontal offset (positive moves right, negative moves left)
    local yOffset = -40                 -- Vertical offset (positive moves up, negative moves down)
    local arrowHeadLength = 10         -- Length of the arrowhead sides
    local arrowHeadWidth = 8          -- Width of the arrowhead base (positive value)
    
    -- Define manual offset parameters for each direction
    local direction1yoffset = 40        -- Manual Y offset for first "V"
    local direction1xoffset = 10         -- Manual X offset for first "V"
    local direction2yoffset = 30         -- Manual Y offset for second "V"
    local direction2xoffset = 10         -- Manual X offset for second "V"
    
    -- Define direction multipliers for two arrowheads
    -- First arrow pointing down and to the right
    local direction1 = {
        upOrDown = 1,       -- -1 for "Down", 1 for "Up"
        leftOrRight = 1      -- 1 for "Right", -1 for "Left"
    }
    
    -- Second arrow pointing up and to the left (mirrored)
    local direction2 = {
        upOrDown = 1,        -- 1 for "Up", -1 for "Down"
        leftOrRight = -1     -- -1 for "Left", 1 for "Right"
    }
    
    -- Ensure N is a multiple of 4 for symmetry
    if N % 4 ~= 0 then
        N = math.floor(N / 4) * 4
        if N < 4 then
            N = 4
        end
    end
    
    -- Number of points per arrowhead side
    local pointsPerArrow = math.floor(N / 4) -- Each arrow has two sides: left and right
    pointsPerArrow = math.max(1, pointsPerArrow)
    
    -- Generate first arrowhead (pointing down and to the right) with manual offsets
    local arrow1Points = generateArrowHead(
        pointsPerArrow * 2,
        direction1,
        FIXED_ROTATION_ANGLE,
        xOffset + direction1xoffset,    -- Apply manual X offset
        yOffset + direction1yoffset,    -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Compute yOffset for the second arrowhead (pointing up and to the left)
    local yOffset2 = yOffset + (arrowHeadLength * direction1.upOrDown) + direction2yoffset
    
    -- Compute xOffset for the second arrowhead
    local xOffset2 = xOffset + direction2xoffset
    
    -- Generate second arrowhead (mirrored, pointing up and to the left) with manual offsets
    local arrow2Points = generateArrowHead(
        pointsPerArrow * 2,
        direction2,
        FIXED_ROTATION_ANGLE + 180,   -- Rotate by 180 degrees to mirror
        xOffset2,                      -- Apply manual X offset
        yOffset2,                      -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Combine points from both arrowheads to form a diamond
    for _, point in ipairs(arrow1Points) do
        table.insert(points, point)
    end
    
    for _, point in ipairs(arrow2Points) do
        table.insert(points, point)
    end
    
    return points
end,


U_Shape = function(N)
    local points = {}
    
    -- Define parameters
    local FIXED_ROTATION_ANGLE = 41    -- Degrees: Adjust as desired
    local xOffset = 15                  -- Horizontal offset (positive moves right, negative moves left)
    local yOffset = -15                 -- Vertical offset (positive moves up, negative moves down)
    local arrowHeadLength = 4       -- Length of the arrowhead sides
    local arrowHeadWidth = 6           -- Width of the arrowhead base (positive value)
    
    -- Define manual offset parameters for each "U"
    local direction1yoffset = 20         -- Manual Y offset for first "U"
    local direction1xoffset = -20         -- Manual X offset for first "U"
    local direction2yoffset = 10         -- Manual Y offset for second "U"
    local direction2xoffset = -10         -- Manual X offset for second "U"
    
    -- Define direction multipliers for two "U" shapes
    -- First "U" pointing down and to the right
    local direction1 = {
        upOrDown = 1,       -- -1 for "Down", 1 for "Up"
        leftOrRight = 1      -- 1 for "Right", -1 for "Left"
    }
    
    -- Second "U" pointing up and to the left (mirrored)
    local direction2 = {
        upOrDown = 1,        -- 1 for "Up", -1 for "Down"
        leftOrRight = 1     -- -1 for "Left", 1 for "Right"
    }

        
    -- Ensure N is a multiple of 6 for symmetry (since each "U" has three segments)
    if N % 4 ~= 0 then
        N = math.floor(N / 4) * 4
        if N < 4 then
            N = 4
        end
    end

    -- Number of points per "U" shape
    local pointsPerU = math.floor(N / 2) -- Each "U" has two "U" segments (left and right)
    pointsPerU = math.max(6, pointsPerU) -- Ensure enough points for smoothness (minimum 20)
    
    -- Generate first "U" shape (pointing down and to the right) with manual offsets
    local U1Points = generateUShape(
        pointsPerU,
        direction1,
        FIXED_ROTATION_ANGLE,
        xOffset + direction1xoffset,    -- Apply manual X offset
        yOffset + direction1yoffset,    -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Generate second "U" shape (pointing up and to the left) with manual offsets and rotation
    local U2Points = generateUShape(
        pointsPerU,
        direction2,
        FIXED_ROTATION_ANGLE + 180,   -- Rotate by 180 degrees to mirror
        xOffset + direction2xoffset,    -- Apply manual X offset
        yOffset + direction2yoffset,    -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Combine points from both "U" shapes to form a diamond
    for _, point in ipairs(U1Points) do
        table.insert(points, point)
    end
    
    for _, point in ipairs(U2Points) do
        table.insert(points, point)
    end
    
    return points
end,


Diamond_Crystal = function(N)
    local points = {}
    
    -- Define parameters
    local FIXED_ROTATION_ANGLE = 32    -- Degrees: Adjust as desired
    local xOffset = -10                 -- Horizontal offset (positive moves right, negative moves left)
    local yOffset = -40                 -- Vertical offset (positive moves up, negative moves down)
    local arrowHeadLength = 10         -- Length of the arrowhead sides
    local arrowHeadWidth = 5        -- Width of the arrowhead base (positive value)
    
    -- Define manual offset parameters for each direction
    local direction1yoffset = 40        -- Manual Y offset for first "V"
    local direction1xoffset = 10         -- Manual X offset for first "V"
    local direction2yoffset = 30         -- Manual Y offset for second "V"
    local direction2xoffset = 10         -- Manual X offset for second "V"
    
    -- Define direction multipliers for two arrowheads
    -- First arrow pointing down and to the right
    local direction1 = {
        upOrDown = 1,       -- -1 for "Down", 1 for "Up"
        leftOrRight = 1      -- 1 for "Right", -1 for "Left"
    }
    
    -- Second arrow pointing up and to the left (mirrored)
    local direction2 = {
        upOrDown = 1,        -- 1 for "Up", -1 for "Down"
        leftOrRight = -1     -- -1 for "Left", 1 for "Right"
    }
    
    -- Ensure N is a multiple of 4 for symmetry
    if N % 4 ~= 0 then
        N = math.floor(N / 4) * 4
        if N < 4 then
            N = 4
        end
    end
    
    -- Number of points per arrowhead side
    local pointsPerArrow = math.floor(N / 4) -- Each arrow has two sides: left and right
    pointsPerArrow = math.max(1, pointsPerArrow)
    
    -- Generate first arrowhead (pointing down and to the right) with manual offsets
    local arrow1Points = generateArrowHead(
        pointsPerArrow * 2,
        direction1,
        FIXED_ROTATION_ANGLE,
        xOffset + direction1xoffset,    -- Apply manual X offset
        yOffset + direction1yoffset,    -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Compute yOffset for the second arrowhead (pointing up and to the left)
    local yOffset2 = yOffset + (arrowHeadLength * direction1.upOrDown) + direction2yoffset
    
    -- Compute xOffset for the second arrowhead
    local xOffset2 = xOffset + direction2xoffset
    
    -- Generate second arrowhead (mirrored, pointing up and to the left) with manual offsets
    local arrow2Points = generateArrowHead(
        pointsPerArrow * 2,
        direction2,
        FIXED_ROTATION_ANGLE + 180,   -- Rotate by 180 degrees to mirror
        xOffset2,                      -- Apply manual X offset
        yOffset2,                      -- Apply manual Y offset
        arrowHeadLength,
        arrowHeadWidth
    )
    
    -- Combine points from both arrowheads to form a diamond
    for _, point in ipairs(arrow1Points) do
        table.insert(points, point)
    end
    
    for _, point in ipairs(arrow2Points) do
        table.insert(points, point)
    end
    
    return points
end,


    -- Star Cursor Pattern
    Vibrant_Cursor = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the star)
        local xOffset = 1    -- Horizontal offset
        local yOffset = -10    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            local radius = (i % 2 == 1) and 2 or 4
            local x = math.cos(angle) * radius + xOffset
            local y = math.sin(angle) * radius + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,

    
 -- Cursor (Arrow) Pattern with Fixed Angle, Direction Controls, and Position Offsets
 Broom = function(N)
    local points = {}
 
    local arrowUpOrDown = 1          -- Positive for "Up", Negative for "Down"
    local arrowLeftOrRight = 1       -- Positive for "Right", Negative for "Left"
  
    local FIXED_ROTATION_ANGLE = 49   -- Adjust this value to rotate the cursor pattern as desired

    local xOffset = 21                -- Horizontal offset (positive moves right, negative moves left)
    local yOffset = -15               -- Vertical offset (positive moves up, negative moves down)

    local shaftLength = 20          -- Increased for visibility
    
    local shaftWidth = 10              -- Currently not directly used but can influence visual spacing
    
    local arrowHeadLength = 30        -- Increase for longer arrowhead sides; decrease for shorter sides
    
    local arrowHeadWidth = 1         -- Increase for a wider arrowhead base; decrease for a narrower base
    
    local verticalMultiplier = sign(arrowUpOrDown)

    local horizontalMultiplier = sign(arrowLeftOrRight)
    
    local radiansOffset = math.rad(FIXED_ROTATION_ANGLE or 45) -- Defaults to 45° if not defined

    local shaftPoints = math.floor(N * 0.6)
    
    local arrowHeadPoints = math.floor((N - shaftPoints) / 2)

    shaftPoints = math.max(1, shaftPoints)
    arrowHeadPoints = math.max(1, arrowHeadPoints)

    for i = 1, shaftPoints do
        -- Calculate the Y-coordinate based on the current point's position along the shaft
        local y = (i / shaftPoints) * shaftLength * verticalMultiplier
        
        -- The X-coordinate remains 0 as the shaft is centered vertically
        local x = 0
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset

        table.insert(points, { x = rotatedX, y = rotatedY })
    end

    for i = 1, arrowHeadPoints do
        -- Calculate the ratio of the current point's position within the arrowhead
        local ratio = i / arrowHeadPoints
        
        -- Calculate the X and Y coordinates for the left side of the arrowhead
        local x = -arrowHeadWidth * (1 - ratio) * horizontalMultiplier
        local y = (shaftLength + arrowHeadLength * ratio) * verticalMultiplier
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset
        
        -- Insert the rotated and offset point into the points table
        table.insert(points, { x = rotatedX, y = rotatedY })
    end
    
 
    for i = 1, arrowHeadPoints do
        -- Calculate the ratio of the current point's position within the arrowhead
        local ratio = i / arrowHeadPoints
        
        -- Calculate the X and Y coordinates for the right side of the arrowhead
        local x = arrowHeadWidth * (1 - ratio) * horizontalMultiplier
        local y = (shaftLength + arrowHeadLength * ratio) * verticalMultiplier
        
        -- Apply rotation to the (x, y) point
        local rotatedX = x * math.cos(radiansOffset) - y * math.sin(radiansOffset)
        local rotatedY = x * math.sin(radiansOffset) + y * math.cos(radiansOffset)
        
        -- Apply position offsets to shift the entire pattern
        rotatedX = rotatedX + xOffset
        rotatedY = rotatedY + yOffset
        

        table.insert(points, { x = rotatedX, y = rotatedY })
    end
    

    return points
end,


    -- Custom Star Pattern for Unique Shapes
    Custom_Star_Pattern = function(N)
        local points = {}
        local angleStep = (2 * math.pi) / N

        -- Position Offsets (Adjust these to move the custom star)
        local xOffset = 0    -- Horizontal offset
        local yOffset = 0    -- Vertical offset

        for i = 1, N do
            local angle = (i - 1) * angleStep
            local radius = (i % 2 == 1) and 30 or 15
            local x = math.cos(angle) * radius + xOffset
            local y = math.sin(angle) * radius + yOffset
            table.insert(points, { x = x, y = y })
        end
        return points
    end,
}

-- For safety, unify references:
EasyCursorTrails.glowPatterns = EasyCursorTrails.dynamicPatterns



---------------------------------------------------------------------------
-- Mapping short texture names -> pattern key
---------------------------------------------------------------------------
-- Mapping short texture names -> pattern key
EasyCursorTrails.cursorGlowMapping = {
    ["Pearl"]                 = "Diamond",
    ["Alien3"]                = "Star_Cursor",
    ["BroomStick1"]           = "Broom",
    ["Bullet1"]               = "Bullet1",
    ["vibrant_sniper_scope"]  = "Circle_White",
    ["sniper_scope"]          = "Circle_White",
    ["sniper_scope4"]        = "Circle_White",
    ["dirty_lens"]            = "Circle_White",
    ["Circle1"]              = "Circle_White",
    ["Circle2"]              = "Circle_White",
    ["Circle3"]              = "Circle_White",
    ["Circle4"]              = "Circle_White",
    ["Circle5"]              = "Circle_White",
    ["Circle_thin_mid"]       = "Circle_White",
    ["Circle_White"]          = "Circle_White",
    ["2_Semi_Circle_2"]       = "U_Shape",
    ["2_Semi_Circle_5"]       = "U_Shape",
    ["Diamond_Left"]          = "Diamond",
    ["Diamond_Crystal"]        = "Diamond_Crystal",
    ["Glass1"]               = "Circle_White",
    ["Glass2"]               = "Circle_White",
    ["cursor1"]              = "Cursor_Arrow_Pattern",
    ["cursor2"]              = "Vibrant_Cursor",
    ["Golden_Ring"]          = "Circle_White",
    ["Golden_Heart"]          = "Heart_1",
    ["Heart_White"]           = "Heart_1",
    ["Heart3"]               = "Heart_1",
    ["Heart5"]               = "Heart_1",
    ["Heart7"]               = "Heart_1",
    ["RGB_Rotate_1"]          = "Circle_White",
    ["Yin_Yang_v1"]          = "Circle_White",
    ["Yin_Yang_1"]          = "Circle_White",
    ["Radar_1"]                 = "Circle_White",
    ["Circle_1_Hovering"]     = "Circle_White",
    ["Circle_focus_1"]          = "Circle_White",
    ["Butterfly_1"]          = "Star_Cursor",
    ["Fairy_Left_1_Hovering"]       = "Star_Cursor",
}



---------------------------------------------------------------------------
-- Trail Textures
---------------------------------------------------------------------------
EasyCursorTrails.trailTextures = {
    [1] = {
        { name = "Star1",   texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Star\\Star1.tga" },
        { name = "Glitter", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Star\\Glitter.tga" },
        { name = "Lines",   texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Star\\lines_trail.tga" },
        { name = "Dust",    texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Star\\Bright_Dust.blp" },
    },
    [2] = {
        { name = "Bubble1", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Bubble\\Bubble1.tga" },
        { name = "Bubble2", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Bubble\\Bubble2.tga" },
        { name = "Bubble3", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Bubble\\Bubble3.tga" },
        { name = "Bubble4", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Bubble\\Bubble4.tga" },
        { name = "Bubble5", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Bubble\\Bubble5.tga" },
    },
    [3] = {
        { name = "Circle1_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle1_Trail.tga" },
        { name = "Circle2_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle2_Trail.tga" },
        { name = "Circle3_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle3_Trail.tga" },
        { name = "Seeds",         texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Seeds.tga" },
        { name = "Circle1",       texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle1.tga" },
        { name = "Circle2",       texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle2.tga" },
        { name = "Circle3",       texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle3.tga" },
        { name = "Circle4",       texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle4.tga" },
        { name = "Circle5",       texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Circle\\Circle5.tga" },
    },
    [4] = {
        { name = "Fairies1_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Fairies1_Trail.tga" },
        { name = "Fairies",        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Faries1.blp" },
        { name = "Fairy",          texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Fairy_Trail.blp" },
        { name = "Fire1",          texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Fire1.tga" },
        { name = "Ghost",          texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\ghost.tga" },
        { name = "Alien",         texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Alien3.blp" },
    },
    [5] = {
        { name = "Heart1_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Heart\\Heart1_Trail.tga" },
        { name = "Heart4_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Heart\\Heart4_Trail.tga" },
    },
    [6] = {
        { name = "Magic_Ball_Trail", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Magic_Ball_Trail.tga" },
        { name = "Flames",           texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Flames.tga" },
        { name = "Fire1",            texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Fire1.tga" },
        { name = "Dust",             texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Bright_Dust.blp" },
    },
    [7] = {
        { name = "Rain",  texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\Rain.tga" },
        { name = "Leaf1", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\Leaf1.tga" },
        { name = "Leaf2", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\Leaf2.tga" },
        { name = "Leaf3", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\Leaf3.tga" },
        { name = "Seeds", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\Seeds.tga" },
    },
    [8] = {
        { name = "Bullet",        texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Military\\Bullet_Sparks.tga" },
        { name = "Bullet Sparks", texture = "Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Military\\Bullet1.blp" },
    },
}

-- Simple text-based table for selecting trail “Effect” categories
local trailEffects = {
    "Star",
    "Bubble",
    "Circle",
    "Fantasy",
    "Heart",
    "Magic",
    "Nature",
    "Military",
}

-- Color Effects Options (for the cursor, simplified):
local colorEffects = {
    { text = "None" },
    { text = "Rainbow" },
    { text = "Pulsing" },
    { text = "Rainbow + Pulsing" },
    { text = "Custom Color Only" },
    { text = "Custom + Pulsing" },
}

---------------------------------------------
-- 24 color effects for the trail
---------------------------------------------
local TrailcolorEffects = {
    { text = "None" },                     -- 1
    { text = "Rainbow" },                  -- 2
    { text = "Pulsing" },                  -- 3
    { text = "Glow" },                     -- 4
    { text = "Rainbow + Pulsing" },        -- 5
    { text = "Glow + Rainbow + Pulsing" }, -- 6
    { text = "Custom Color Only" },        -- 7
    { text = "Custom + Pulsing" },         -- 8
    { text = "Custom + Glow" },            -- 9
    { text = "Custom + Glow + Pulsing" },  -- 10
    { text = "Code-based Magic" },         -- 11
    { text = "Nebula Swirl" },             -- 12
    { text = "Galactic Plasma" },          -- 13
    { text = "Stardust Explosion" },       -- 14
    { text = "Dark Matter" },              -- 15
    { text = "Aurora Borealis" },          -- 16
    { text = "Crackling Electricity" },    -- 17
    { text = "Psychedelic Spiral" },       -- 18
    { text = "Inferno Pulse" },            -- 19
    { text = "Heavenly Glow" },            -- 20
    { text = "Midnight Spark" },           -- 21
    -- (and so forth)
}

-- Movement Effects
local trailMovementEffectOptions = {
    { text = "Linear Separation" },
    { text = "Curling Effect" },
    { text = "Wave" },
    { text = "Flag" },
    { text = "Echo" },
    { text = "Zig Zag" },
    { text = "Spiral" },
    { text = "Explosion" },
    { text = "Random Scatter" },
    { text = "Circular Orbit" },
    { text = "Heartbeat" },
    { text = "Sine Wave" },
    { text = "Swirl" },
    { text = "Bounce" },
    { text = "Pulse" },
    { text = "Helix" },
    { text = "Firework" },
    { text = "Rain" },
    { text = "Comet" },
    { text = "Galaxy" },
    { text = "Twinkle" },
    { text = "Flare" },
    { text = "Ripple" },
    { text = "Smoke" },
    { text = "Meteor Shower" },
    { text = "Pendulum" },
    { text = "DNA Strand" },
    { text = "Lightning" },
    { text = "Orbiting Layers" },
    { text = "Waterfall" },
    { text = "Vortex" },
    { text = "Tunnel" },
    { text = "Strobe" },
    { text = "Sunburst" },
    { text = "Fountain" },
    { text = "Motion Blur" },
    { text = "Connected Glow" },
    { text = "Burning Rocket" },
    { text = "Lightning Effect" },
    { text = "Rain Effect" },
    { text = "Flame Effect" },
    { text = "Ghost Effect" },
}

--------------------------------------------------
-- Validate booleans
--------------------------------------------------
local function validateBooleanSetting(key, defaultValue)
    local val = EasyCursorTrailsDB[key]
    if type(val) ~= "boolean" then
        EasyCursorTrailsDB[key] = defaultValue
    end
end

local function InitializeSavedVariables()
    if not EasyCursorTrailsDB then
        EasyCursorTrailsDB = {}
    end

    -- Fill missing keys from defaults
    for key, defaultValue in pairs(defaults) do
        if EasyCursorTrailsDB[key] == nil then
            EasyCursorTrailsDB[key] = defaultValue
        end
    end

    local function validateNumericSetting(key, minValue, maxValue, defaultValue)
        EasyCursorTrailsDB[key] = tonumber(EasyCursorTrailsDB[key]) or defaultValue
        local val = EasyCursorTrailsDB[key]
        if val < minValue or val > maxValue then
            print(string.format("EasyCursorTrails Warning: '%s' out of range (%.2f..%.2f). Resetting to %.2f.",
                key, minValue, maxValue, defaultValue
            ))
            EasyCursorTrailsDB[key] = defaultValue
        end
    end

    -- Validate numeric settings
    validateNumericSetting("glowIntensity",         0,   1,   defaults.glowIntensity)
    validateNumericSetting("glowRadius",            0.1, 1,   defaults.glowRadius)
    validateNumericSetting("glowSize",              0.1, 5,   defaults.glowSize)
    validateNumericSetting("glowThickness",         0.1, 1,   defaults.glowThickness)
    validateNumericSetting("patternGlowCount",      1,   40,  defaults.patternGlowCount)
    validateNumericSetting("glowHollowness",        0.0, 1.0, defaults.glowHollowness)
    validateNumericSetting("glowPulsingIntensity",  0,   1,   defaults.glowPulsingIntensity)
    validateNumericSetting("pulsingSpeed",          0,   10,  defaults.pulsingSpeed)
    validateNumericSetting("trailSizeStart",        1,   500, defaults.trailSizeStart)
    validateNumericSetting("trailSizeEnd",          10,  500, defaults.trailSizeEnd)
    validateNumericSetting("trailCount",            1,   500, defaults.trailCount)
    validateNumericSetting("trailLayerCount",       1,   50,  defaults.trailLayerCount)
    validateNumericSetting("trailLayerSpacing",     0,   500, defaults.trailLayerSpacing)
    validateNumericSetting("trailInitialSeparation",0,   200, defaults.trailInitialSeparation)
    validateNumericSetting("trailDelay",            0.1, 5.0, defaults.trailDelay)
    validateNumericSetting("cursorSize",            10,  200, defaults.cursorSize)
    validateNumericSetting("trailOffsetX",         -100, 100, defaults.trailOffsetX)
    validateNumericSetting("trailOffsetY",         -100, 100, defaults.trailOffsetY)
    validateNumericSetting("cursorOffsetX",        -100, 100, defaults.cursorOffsetX)
    validateNumericSetting("cursorOffsetY",        -100, 100, defaults.cursorOffsetY)

    -- Validate booleans
    validateBooleanSetting("disableGlowPulsing", defaults.disableGlowPulsing)
    validateBooleanSetting("glowAboveCursor",    defaults.glowAboveCursor)
    validateBooleanSetting("enableTrails",       defaults.enableTrails)

    -- Additional init
    EasyCursorTrailsDB.colorIndexCursor     = EasyCursorTrailsDB.colorIndexCursor     or defaults.colorIndexCursor
    EasyCursorTrailsDB.pulseDirectionCursor = EasyCursorTrailsDB.pulseDirectionCursor or defaults.pulseDirectionCursor
    EasyCursorTrailsDB.pulseValueCursor     = EasyCursorTrailsDB.pulseValueCursor     or defaults.pulseValueCursor

    EasyCursorTrailsDB.cursorOffsetX   = EasyCursorTrailsDB.cursorOffsetX   or 0
    EasyCursorTrailsDB.cursorOffsetY   = EasyCursorTrailsDB.cursorOffsetY   or 0
    EasyCursorTrailsDB.glowAboveCursor = EasyCursorTrailsDB.glowAboveCursor or false
    EasyCursorTrailsDB.glowColor       = EasyCursorTrailsDB.glowColor       or { r = 1, g = 1, b = 1, a = 1 }
    EasyCursorTrailsDB.glowIntensity   = EasyCursorTrailsDB.glowIntensity   or 0.5

    -- Initialize colorIndexTrail in the main table
    EasyCursorTrails.colorIndexTrail = EasyCursorTrails.colorIndexTrail or 0
end




local function CreateSlider(name, parent, label, min, max, step, value, onValueChanged)
    local slider = CreateFrame("Slider", name, parent, "OptionsSliderTemplate")
    slider:SetMinMaxValues(min, max)
    slider:SetValueStep(step)
    slider:SetValue(value)
    slider.text = slider:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    slider.text:SetPoint("BOTTOM", slider, "TOP", 0, 0)
    slider.text:SetText(label .. ": " .. tostring(value))
    
    slider:SetScript("OnValueChanged", function(self, newValue)
        onValueChanged(self, newValue)
    end)
    
    return slider
end



local function CreateDropdown(name, parent, labelText, options, currentValue, onSelect)
        local label = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        label:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -10)
        label:SetText(labelText)
    
        local dropdown = CreateFrame("Frame", name, parent, "UIDropDownMenuTemplate")
        dropdown:SetPoint("TOPLEFT", label, "BOTTOMLEFT", 0, -10)
        UIDropDownMenu_SetWidth(dropdown, 200)
    
        local initialText = "Select an option"
        if options and options[currentValue] and options[currentValue].text then
            initialText = options[currentValue].text
        end
        UIDropDownMenu_SetText(dropdown, initialText)
    
        UIDropDownMenu_Initialize(dropdown, function(self, level, menuList)
            if not options or #options == 0 then
                local info = UIDropDownMenu_CreateInfo()
                info.text = "No Options Available"
                info.disabled = true
                UIDropDownMenu_AddButton(info)
                return
            end
    
            for i, option in ipairs(options) do
                local info = UIDropDownMenu_CreateInfo()
                info.text = option.text or "Option " .. i
                if option.icon then
                    info.icon = option.icon
                    info.iconTexCoord = {0, 1, 0, 1}
                    info.iconWidth = 16
                    info.iconHeight = 16
                end
                info.func = function()
                    onSelect(i)
                    UIDropDownMenu_SetText(dropdown, option.text or "Option " .. i)
                    CloseDropDownMenus()
                end
                UIDropDownMenu_AddButton(info)
            end
        end)
    
        print("EasyCursorTrails: Created Dropdown - " .. labelText) -- Debugging print
    
        return dropdown
    end
    
    local function CreateSimpleDropdown(name, parent, labelText, options, currentValue, onSelect)
        local label = parent:CreateFontString(nil, "OVERLAY", "GameFontNormal")
        label:SetPoint("TOPLEFT", parent, "TOPLEFT", 20, -10)
        label:SetText(labelText)
    
        local dropdown = CreateFrame("Frame", name, parent, "UIDropDownMenuTemplate")
        dropdown:SetPoint("TOPLEFT", label, "BOTTOMLEFT", 0, -10)
        UIDropDownMenu_SetWidth(dropdown, 200)
    
        local initialText = "Select an option"
        if options and options[currentValue] and options[currentValue].text then
            initialText = options[currentValue].text
        end
        UIDropDownMenu_SetText(dropdown, initialText)
    
        UIDropDownMenu_Initialize(dropdown, function(self, level, menuList)
            if not options or #options == 0 then
                local info = UIDropDownMenu_CreateInfo()
                info.text = "No Options Available"
                info.disabled = true
                UIDropDownMenu_AddButton(info)
                return
            end
    
            for i, option in ipairs(options) do
                local info = UIDropDownMenu_CreateInfo()
                info.text = option.text or "Option " .. i
                if option.icon then
                    info.icon = option.icon
                    info.iconTexCoord = {0, 1, 0, 1}
                    info.iconWidth = 16
                    info.iconHeight = 16
                end
                info.func = function()
                    onSelect(i)
                    UIDropDownMenu_SetText(dropdown, option.text or "Option " .. i)
                    CloseDropDownMenus()
                end
                UIDropDownMenu_AddButton(info)
            end
        end)
    
        print("EasyCursorTrails: Created Simple Dropdown - " .. labelText) -- Debugging print
    
        return dropdown
    end
-------------------------
-- Color Picker
-------------------------
function EasyCursorTrails.OpenColorPicker(initialColor, callback)
    local function ColorPickerCallback(restore)
        local newR, newG, newB, newA
        if restore then
            newR, newG, newB, newA = unpack(restore)
        else
            newR, newG, newB = ColorPickerFrame:GetColorRGB()
            if ColorPickerFrame.hasOpacity then
                if ColorPickerFrame.opacity then
                    newA = 1 - (ColorPickerFrame.opacity or 0)
                else
                    newA = 1
                end
            else
                newA = 1
            end
        end
        callback({ r = newR, g = newG, b = newB, a = newA })
    end

    ColorPickerFrame.func = ColorPickerCallback
    ColorPickerFrame.opacityFunc = ColorPickerCallback
    ColorPickerFrame.cancelFunc = ColorPickerCallback
    ColorPickerFrame.swatchFunc = ColorPickerCallback

    ColorPickerFrame.hasOpacity = true
    ColorPickerFrame.opacity = 1 - (initialColor.a or 1)
    ColorPickerFrame.previousValues = { initialColor.r, initialColor.g, initialColor.b, initialColor.a }

    if ColorPickerFrame.SetColorRGB then
        ColorPickerFrame:SetColorRGB(initialColor.r, initialColor.g, initialColor.b)
    else
        ColorPickerFrame.red = initialColor.r
        ColorPickerFrame.green = initialColor.g
        ColorPickerFrame.blue = initialColor.b
    end

    ColorPickerFrame:Hide()
    ColorPickerFrame:Show()
end

-------------------------
-- Basic Utility
-------------------------
local ColorUtil = {}
function ColorUtil.GetRGBFromHSL(h, s, l)
    local r, g, b

    if s == 0 then
        r, g, b = l, l, l
    else
        local function hue2rgb(p, q, t)
            if t < 0 then t = t + 1 end
            if t > 1 then t = t - 1 end
            if t < 1/6 then return p + (q - p) * 6 * t end
            if t < 1/2 then return q end
            if t < 2/3 then return p + (q - p) * (2/3 - t) * 6 end
            return p
        end

        local q = l < 0.5 and l * (1 + s) or l + s - l * s
        local p = 2 * l - q
        r = hue2rgb(p, q, h + 1/3)
        g = hue2rgb(p, q, h)
        b = hue2rgb(p, q, h - 1/3)
    end

    return r, g, b
end

EasyCursorTrails.DebugPrint = function(message)
    if EasyCursorTrailsDB.debugMode then
        print("|cff00ff00EasyCursorTrails Debug:|r " .. tostring(message))
    end
end

EasyCursorTrails.HandleError = function(message)
    print("|cffff0000EasyCursorTrails Error:|r " .. tostring(message))
end

-------------------------
-- Pulsing Logic (Updated)
-------------------------
function EasyCursorTrails.UpdatePulseValue()
    -- Ensure these variables are never nil:
    if not EasyCursorTrails.pulseValueTrail then
        EasyCursorTrails.pulseValueTrail = 0.5
    end
    if not EasyCursorTrails.pulseDirectionTrail then
        EasyCursorTrails.pulseDirectionTrail = 1
    end

    -- Then proceed with the existing logic
    local pulseStep = 0.05
    local pulseMin  = 0.3
    local pulseMax  = 1.2

    EasyCursorTrails.pulseValueTrail =
        EasyCursorTrails.pulseValueTrail
        + (EasyCursorTrails.pulseDirectionTrail * pulseStep)

    if EasyCursorTrails.pulseValueTrail > pulseMax then
        EasyCursorTrails.pulseValueTrail = pulseMax
        EasyCursorTrails.pulseDirectionTrail = -1
    elseif EasyCursorTrails.pulseValueTrail < pulseMin then
        EasyCursorTrails.pulseValueTrail = pulseMin
        EasyCursorTrails.pulseDirectionTrail = 1
    end
end

function EasyCursorTrails.UpdateRainbowColor(indexOffset)
    local offset = indexOffset or 0

    -- Retrieve and validate maximumOffset
    local maximumOffset = tonumber(EasyCursorTrailsDB.trailLayerSpacing) or 30
    if type(maximumOffset) ~= "number" then
        EasyCursorTrails.HandleError("maximumOffset is not a number! Resetting to default value.")
        maximumOffset = 30 -- Default value
    end

    EasyCursorTrails.colorIndexTrail = (EasyCursorTrails.colorIndexTrail or 0) + 0.03
    local hue = EasyCursorTrails.colorIndexTrail + offset

    local rr = 0.5 + 0.5 * math.sin(hue)
    local gg = 0.5 + 0.5 * math.sin(hue + 2)
    local bb = 0.5 + 0.5 * math.sin(hue + 4)
    return rr, gg, bb
end



-------------------------------
-- ApplyColorEffectTrail
-------------------------------
function EasyCursorTrails.ApplyColorEffectTrail(trail, index)
    if not (trail and trail.texture) then
        EasyCursorTrails.HandleError("ApplyColorEffectTrail: 'trail' or 'trail.texture' is nil.")
        return
    end

    -- Ensure colorIndexTrail is initialized
    EasyCursorTrails.colorIndexTrail = EasyCursorTrails.colorIndexTrail or 0

    local glowColor = EasyCursorTrailsDB.glowColor or { r = 1, g = 1, b = 1, a = 1 }
    local intensity = EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity

    trail.texture:SetVertexColor(glowColor.r, glowColor.g, glowColor.b, glowColor.a * intensity)
    trail.texture:SetAlpha(glowColor.a * intensity)

    -- Create a sub-frame for glow if needed
    if not trail.glowEffect then
        local glow = CreateFrame("Frame", nil, trail)
        glow:SetFrameLevel(trail:GetFrameLevel() - 1)
        glow:SetPoint("CENTER", trail, "CENTER")
        glow:SetSize(trail:GetWidth() * 3, trail:GetHeight() * 3)

        local glowTex = glow:CreateTexture(nil, "OVERLAY")
        glowTex:SetTexture("Interface\\GLUES\\MODELS\\UI_Draenei\\GenericGlow64")
        glowTex:SetBlendMode("ADD")
        glowTex:SetAllPoints()
        glow.texture = glowTex

        glow:Hide()
        trail.glowEffect = glow
    end

    local glow = trail.glowEffect
    local effect = EasyCursorTrailsDB.trailColorEffect or 1
    local trailColor = EasyCursorTrailsDB.trailColor or { r = 1, g = 1, b = 1, a = 1 }
    local r, g, b, a = 1, 1, 1, 1
    local showGlow = false

    -- The big if-else (1..21)
    if effect == 1 then
        r, g, b, a = 1, 1, 1, 1
    elseif effect == 2 then
        if index ~= nil then
            r, g, b = EasyCursorTrails.UpdateRainbowColor(index * 10.5)
        else
            r, g, b = 1, 1, 1
        end

    elseif effect == 3 then
        EasyCursorTrails.UpdatePulseValue()
        r, g, b, a = EasyCursorTrails.pulseValueTrail, EasyCursorTrails.pulseValueTrail, EasyCursorTrails.pulseValueTrail, 1
    elseif effect == 4 then
        r, g, b, a = 1, 1, 1, 0.9
        showGlow = true
    elseif effect == 5 then
        EasyCursorTrails.UpdatePulseValue()
        if index ~= nil then
            local rr, gg, bb = EasyCursorTrails.UpdateRainbowColor(index * 10.2)
            r = rr * EasyCursorTrails.pulseValueTrail
            g = gg * EasyCursorTrails.pulseValueTrail
            b = bb * EasyCursorTrails.pulseValueTrail
        else
            r, g, b = 1, 1, 1
        end
        a = 1
    elseif effect == 6 then
        EasyCursorTrails.UpdatePulseValue()
        if index ~= nil then
            local rr, gg, bb = EasyCursorTrails.UpdateRainbowColor(index * 10.5)
            r = rr * EasyCursorTrails.pulseValueTrail
            g = gg * EasyCursorTrails.pulseValueTrail
            b = bb * EasyCursorTrails.pulseValueTrail
        else
            r, g, b = 1, 1, 1
        end
        a = 1
        showGlow = true
        if glow and glow.texture then
            glow.texture:SetVertexColor(r, g, b, 0.6)
        end
    elseif effect == 7 then
        r, g, b, a = trailColor.r, trailColor.g, trailColor.b, trailColor.a
    elseif effect == 8 then
        EasyCursorTrails.UpdatePulseValue()
        r = trailColor.r * EasyCursorTrails.pulseValueTrail
        g = trailColor.g * EasyCursorTrails.pulseValueTrail
        b = trailColor.b * EasyCursorTrails.pulseValueTrail
        a = trailColor.a
    elseif effect == 9 then
        r, g, b, a = trailColor.r, trailColor.g, trailColor.b, 0.8
        showGlow = true
    elseif effect == 10 then
        EasyCursorTrails.UpdatePulseValue()
        r = trailColor.r * EasyCursorTrails.pulseValueTrail
        g = trailColor.g * EasyCursorTrails.pulseValueTrail
        b = trailColor.b * EasyCursorTrails.pulseValueTrail
        a = trailColor.a
        showGlow = true
        if glow and glow.texture then
            glow.texture:SetVertexColor(r, g, b, 0.6)
        end
    elseif effect == 11 then
        EasyCursorTrails.UpdatePulseValue()
        if index ~= nil then
            local rr, gg, bb = EasyCursorTrails.UpdateRainbowColor(index * 0.5)
            r = rr * EasyCursorTrails.pulseValueTrail
            g = gg * EasyCursorTrails.pulseValueTrail
            b = bb * EasyCursorTrails.pulseValueTrail
        else
            r, g, b = 1, 1, 1
        end
        a = 1
        showGlow = true
        if glow and glow.texture then
            glow.texture:SetVertexColor(r, g, b, 0.7)
        end
    elseif effect == 12 then
        r, g, b, a = 0.5 + 0.5 * math.sin(EasyCursorTrails.colorIndexTrail),
                     0.5 + 0.5 * math.sin(EasyCursorTrails.colorIndexTrail + 1.5),
                     0.5 + 0.5 * math.sin(EasyCursorTrails.colorIndexTrail + 3),
                     0.8
        trail:SetSize(trail.originalSize * 1.5, trail.originalSize * 1.5)
        showGlow = true
    elseif effect == 13 then
        r, g, b, a = 0.3 + 0.7 * math.abs(math.sin(EasyCursorTrails.colorIndexTrail)),
                     0.2 + 0.8 * math.abs(math.cos(EasyCursorTrails.colorIndexTrail)),
                     0.5 + 0.5 * math.abs(math.sin(EasyCursorTrails.colorIndexTrail * 1.5)),
                     0.9
        trail:SetSize(trail.originalSize * 1.2, trail.originalSize * 1.2)
        showGlow = true
    elseif effect == 14 then
        r, g, b, a = 1, 1, 1, EasyCursorTrails.pulseValueTrail
        trail:SetSize(trail.originalSize * 2.0, trail.originalSize * 2.0)
        showGlow = true
    elseif effect == 15 then
        r, g, b, a = 0.2, 0.1, 0.3, 0.7
        trail:SetSize(trail.originalSize * 1.5, trail.originalSize * 1.5)
        showGlow = true
    elseif effect == 16 then
        r, g, b, a = 0.2 + 0.8 * math.sin(EasyCursorTrails.colorIndexTrail),
                     0.5 + 0.5 * math.sin(EasyCursorTrails.colorIndexTrail + 2),
                     0.7 + 0.3 * math.sin(EasyCursorTrails.colorIndexTrail + 4),
                     0.85
        trail:SetSize(trail.originalSize * 1.3, trail.originalSize * 1.3)
        showGlow = true
    elseif effect == 17 then
        r, g, b, a = 0.8, 0.8, 1.0, EasyCursorTrails.pulseValueTrail
        trail:SetSize(trail.originalSize * 1.7, trail.originalSize * 0.3)
        showGlow = true
    elseif effect == 18 then
        r, g, b, a = 0.6 + 0.4 * math.sin(EasyCursorTrails.colorIndexTrail * 2),
                     0.6 + 0.4 * math.cos(EasyCursorTrails.colorIndexTrail * 2),
                     0.6 + 0.4 * math.sin(EasyCursorTrails.colorIndexTrail * 3),
                     0.9
        trail:SetSize(trail.originalSize * 1.5, trail.originalSize * 1.5)
        showGlow = true
    elseif effect == 19 then
        r, g, b, a = 1, 0.4, 0.2, EasyCursorTrails.pulseValueTrail
        trail:SetSize(trail.originalSize * 1.6, trail.originalSize * 0.6)
        showGlow = true
    elseif effect == 20 then
        r, g, b, a = 1, 1, 0.8, 0.9
        trail:SetSize(trail.originalSize * 2.0, trail.originalSize * 2.0)
        showGlow = true
    elseif effect == 21 then
        r, g, b, a = 0.3, 0.3, 0.7, EasyCursorTrails.pulseValueTrail
        trail:SetSize(trail.originalSize * 1.4, trail.originalSize * 10.4)
        showGlow = true
    else
        r, g, b, a = 1, 1, 1, 1
        EasyCursorTrails.DebugPrint("ApplyColorEffectTrail: Unknown effect index " .. tostring(effect) .. ". Defaulting to white.")
    end

    -- Ensure colorIndexTrail is a number before using it
    if type(EasyCursorTrails.colorIndexTrail) ~= "number" then
        EasyCursorTrails.HandleError("colorIndexTrail is not a number! Resetting to 0.")
        EasyCursorTrails.colorIndexTrail = 0
    end

    a = math.max(0, math.min(a, 1))
    trail.texture:SetVertexColor(r, g, b, a)
    trail.texture:SetAlpha(a)

    if glow and glow.texture then
        if showGlow then
            glow.texture:SetVertexColor(r, g, b, a)
            glow:Show()
        else
            glow:Hide()
        end
    end
end

-------------------------------------------
-- HSV -> RGB helper
-------------------------------------------
local function HSVtoRGB(h, s, v)
    if s <= 0 then
        return v, v, v
    end
    h = h * 6
    local i = math.floor(h)
    local f = h - i
    local p = v * (1 - s)
    local q = v * (1 - f * s)
    local t = v * (1 - (1 - f) * s)
    i = i % 6

    if i == 0 then
        return v, t, p
    elseif i == 1 then
        return q, v, p
    elseif i == 2 then
        return p, v, t
    elseif i == 3 then
        return p, q, v
    elseif i == 4 then
        return t, p, v
    else
        return v, p, q
    end
end

function EasyCursorTrails.UpdateGlowFrames()
    if not EasyCursorTrails.glowPatterns or not EasyCursorTrails.trailPool then
        EasyCursorTrails.HandleError("UpdateGlowFrames: glowPatterns or trailPool not initialized.")
        return
    end

    for layerIndex, trails in ipairs(EasyCursorTrails.trailPool) do
        if type(trails) == "table" then
            for trailIndex, trail in ipairs(trails) do
                if trail and trail.glowEffect then
                    -- Update glow properties based on saved variables
                    trail.glowEffect:SetBackdropColor(EasyCursorTrailsDB.glowColor.r, EasyCursorTrailsDB.glowColor.g, EasyCursorTrailsDB.glowColor.b, EasyCursorTrailsDB.glowColor.a)
                    -- Add more updates as necessary
                end
            end
        end
    end

    print("EasyCursorTrails: Glow frames updated successfully!")
end

-------------------------------------------
-- ApplyColorEffectCursor
-------------------------------------------
function EasyCursorTrails.ApplyColorEffectCursor()
    if not customCursor or not customCursor.texture then
        EasyCursorTrails.HandleError("customCursor or customCursor.texture not initialized.")
        return
    end

    local glowColor = EasyCursorTrailsDB.glowColor or { r = 1, g = 1, b = 1, a = 1 }
    local intensity = EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity
    customCursor.texture:SetVertexColor(glowColor.r, glowColor.g, glowColor.b, glowColor.a * intensity)
    customCursor.texture:SetAlpha(glowColor.a * intensity)

    local effect      = EasyCursorTrailsDB.cursorColorEffect or 1
    local cursorColor = EasyCursorTrailsDB.cursorColor or { r = 1, g = 1, b = 1, a = 1 }
    customCursor.texture:SetBlendMode("ADD") -- default

    if effect == 1 then
        customCursor.texture:SetVertexColor(1, 1, 1, 1)
    elseif effect == 2 then
        local colorIndex = (customCursor.colorIndexCursor or 0) + 2
        customCursor.colorIndexCursor = colorIndex % 360
        local hue = customCursor.colorIndexCursor / 360
        local r,g,b = HSVtoRGB(hue, 1, 1)
        customCursor.texture:SetVertexColor(r, g, b, cursorColor.a)
    elseif effect == 3 then
        local pulseValue = (customCursor.pulseValueCursor or 0.5)
                         + (customCursor.pulseDirectionCursor or -1)*0.03
        if pulseValue > 1 then
            pulseValue = 1
            customCursor.pulseDirectionCursor = -1
        elseif pulseValue < 0.5 then
            pulseValue = 0.5
            customCursor.pulseDirectionCursor = 1
        end
        customCursor.pulseValueCursor = pulseValue
        local r = cursorColor.r * pulseValue
        local g = cursorColor.g * pulseValue
        local b = cursorColor.b * pulseValue
        customCursor.texture:SetVertexColor(r, g, b, cursorColor.a)
    elseif effect == 4 then
        -- Rainbow + Pulsing
        local colorIndex = (customCursor.colorIndexCursor or 0) + 3.03
        customCursor.colorIndexCursor = colorIndex % 360
        local rad = math.rad(colorIndex)
        local baseR = 0.5 + 0.5 * math.sin(rad)
        local baseG = 0.5 + 0.5 * math.sin(rad + math.rad(120))
        local baseB = 0.5 + 0.5 * math.sin(rad + math.rad(240))

        local pulseValue = (customCursor.pulseValueCursor or 0.5)
                         + (customCursor.pulseDirectionCursor or 1)*0.03
        if pulseValue > 1 then
            pulseValue = 1
            customCursor.pulseDirectionCursor = -1
        elseif pulseValue < 0.1 then
            pulseValue = 0.2
            customCursor.pulseDirectionCursor = 1
        end
        customCursor.pulseValueCursor = pulseValue

        local finalR = baseR * pulseValue
        local finalG = baseG * pulseValue
        local finalB = baseB * pulseValue
        customCursor.texture:SetVertexColor(finalR, finalG, finalB, cursorColor.a)
    elseif effect == 5 then
        customCursor.texture:SetVertexColor(cursorColor.r, cursorColor.g, cursorColor.b, cursorColor.a)
    elseif effect == 6 then
        local pulseValue = (customCursor.pulseValueCursor or 0.5)
                         + (customCursor.pulseDirectionCursor or -1)*0.03
        if pulseValue > 1 then
            pulseValue = 1
            customCursor.pulseDirectionCursor = -1
        elseif pulseValue < 0.5 then
            pulseValue = 0.5
            customCursor.pulseDirectionCursor = 1
        end
        customCursor.pulseValueCursor = pulseValue
        local r = cursorColor.r * pulseValue
        local g = cursorColor.g * pulseValue
        local b = cursorColor.b * pulseValue
        customCursor.texture:SetVertexColor(r, g, b, cursorColor.a)
    elseif effect == 7 then
        -- Glow
        customCursor.texture:SetBlendMode("ADD")
        local alpha = (customCursor.glowAlpha or 0.8)
                    + (customCursor.glowDir or 1)*0.02
        if alpha > 1 then
            alpha = 1
            customCursor.glowDir = -1
        elseif alpha < 0.8 then
            alpha = 0.8
            customCursor.glowDir = 1
        end
        customCursor.glowAlpha = alpha
        customCursor.texture:SetVertexColor(cursorColor.r, cursorColor.g, cursorColor.b, alpha)
    else
        customCursor.texture:SetVertexColor(1, 1, 1, 1)
    end
end

-- Define the UpdateTrailOffsets function within EasyCursorTrails
function EasyCursorTrails.UpdateTrailOffsets()
    -- Validate the existence of trailPool
    if not EasyCursorTrails.trailPool then
        EasyCursorTrails.HandleError("UpdateTrailOffsets: trailPool is not initialized.")
        return
    end

    -- Retrieve and validate offsets from saved variables
    local offsetX = tonumber(EasyCursorTrailsDB.trailOffsetX) or 0
    local offsetY = tonumber(EasyCursorTrailsDB.trailOffsetY) or 0

    -- Iterate through each trail in each layer and update positions
    for layerIndex, layerTrails in ipairs(EasyCursorTrails.trailPool) do
        if type(layerTrails) == "table" then
            for trailIndex, trail in ipairs(layerTrails) do
                if trail and trail.texture then
                    -- Update the trail's position based on offsets
                    -- Adjust the anchoring as per your addon's logic
                    trail.texture:SetPoint("CENTER", UIParent, "BOTTOMLEFT", offsetX, offsetY)
                end
            end
        end
    end

    -- Optionally, update glow frames or other related components
    if EasyCursorTrails.UpdateGlowFrames then
        EasyCursorTrails.UpdateGlowFrames()
    else
        EasyCursorTrails.HandleError("UpdateTrailOffsets: UpdateGlowFrames function is missing.")
    end

    -- Provide feedback for successful update
    print("EasyCursorTrails: Trail offsets updated successfully!")
end


local function InitializeSettingsMenu()
    local menu = CreateFrame("Frame", "EasyCursorTrailsMenu", UIParent, "BasicFrameTemplateWithInset")
    menu:SetSize(650, 880)
    menu:SetPoint("CENTER", UIParent, "CENTER")
    menu:SetMovable(true)
    menu:EnableMouse(true)
    menu:RegisterForDrag("LeftButton")
    menu:SetScript("OnDragStart", menu.StartMoving)
    menu:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
        local point, relativeTo, relativePoint, x, y = self:GetPoint()
        EasyCursorTrailsDB.menuPosition = { point = point, relativePoint = relativePoint, x = x, y = y }
    end)
    menu:Hide()

    if EasyCursorTrailsDB.menuPosition then
        menu:ClearAllPoints()
        menu:SetPoint(
            EasyCursorTrailsDB.menuPosition.point,
            UIParent,
            EasyCursorTrailsDB.menuPosition.relativePoint,
            EasyCursorTrailsDB.menuPosition.x,
            EasyCursorTrailsDB.menuPosition.y
        )
    end

    local function GlowBelowCursorCheckbox()
        if not customCursor or not customCursor.glowEffects then
            print("EasyCursorTrails Error: customCursor or glowEffects not initialized.")
            return
        end
        for _, glow in ipairs(customCursor.glowEffects) do
            if EasyCursorTrailsDB.glowBelow then
                glow:SetFrameStrata("LOW")
            else
                glow:SetFrameStrata("HIGH")
            end
        end
    end

    local menuTitle = menu:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
    menuTitle:SetPoint("TOP", menu, "TOP", 0, -3)
    menuTitle:SetText("Easy Cursor Trails Settings")


    -- Enable Trails
    local enableTrailsCheckbox = CreateFrame("CheckButton", nil, menu, "UICheckButtonTemplate")
    enableTrailsCheckbox:SetPoint("TOPLEFT", menuTitle, "BOTTOMLEFT", 200, -50)
    enableTrailsCheckbox.text = enableTrailsCheckbox:CreateFontString(nil, "OVERLAY", "GameFontNormal")
    enableTrailsCheckbox.text:SetPoint("LEFT", enableTrailsCheckbox, "RIGHT", 5, 0)
    enableTrailsCheckbox.text:SetText("Enable Trails")
    enableTrailsCheckbox:SetChecked(EasyCursorTrailsDB.enableTrails)
    enableTrailsCheckbox:SetScript("OnClick", function(self)
        EasyCursorTrailsDB.enableTrails = self:GetChecked()
        RebuildTrails()
    end)


-- Now define glowBelowCheckbox relative to enableTrailsCheckbox
local glowBelowCheckbox = CreateFrame("CheckButton", nil, menu, "UICheckButtonTemplate")
glowBelowCheckbox:SetPoint("TOPLEFT", enableTrailsCheckbox, "BOTTOMLEFT", -350, 30) -- Adjust as needed
glowBelowCheckbox.text = glowBelowCheckbox:CreateFontString(nil, "OVERLAY", "GameFontNormal")
glowBelowCheckbox.text:SetPoint("LEFT", glowBelowCheckbox, "RIGHT", 5, 0)
glowBelowCheckbox.text:SetText("Glow Below Cursor")
glowBelowCheckbox:SetChecked(EasyCursorTrailsDB.glowBelow or false)
glowBelowCheckbox:SetScript("OnClick", function(self)
    EasyCursorTrailsDB.glowBelow = self:GetChecked()
    GlowBelowCursorCheckbox()
   
end)


    -- Trail Settings
    local trailSettingsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    trailSettingsHeader:SetPoint("TOPLEFT", menuTitle, "BOTTOMLEFT", 200, -20)
    trailSettingsHeader:SetText("Trail Settings")
    

    local trailSizeStartSlider = CreateSlider("TrailSizeStartSlider", menu, "Trail Size Start", 1, 100, 1,
        EasyCursorTrailsDB.trailSizeStart or defaults.trailSizeStart,
        function(slider, value)
            EasyCursorTrailsDB.trailSizeStart = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Size Start: %d", value)
            RebuildTrails()
        end
    )
    trailSizeStartSlider:SetPoint("TOPLEFT", enableTrailsCheckbox, "BOTTOMLEFT", 0, -30)

    local trailSizeEndSlider = CreateSlider("TrailSizeEndSlider", menu, "Trail Size End", 10, 100, 1,
        EasyCursorTrailsDB.trailSizeEnd or defaults.trailSizeEnd,
        function(slider, value)
            EasyCursorTrailsDB.trailSizeEnd = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Size End: %d", value)
            RebuildTrails()
        end
    )
    trailSizeEndSlider:SetPoint("TOPLEFT", trailSizeStartSlider, "BOTTOMLEFT", 0, -30)

    local trailCountSlider = CreateSlider("TrailCountSlider", menu, "Trail Count", 1, 100, 1,
        EasyCursorTrailsDB.trailCount or defaults.trailCount,
        function(slider, value)
            EasyCursorTrailsDB.trailCount = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Count: %d", value)
            RebuildTrails()
        end
    )
    trailCountSlider:SetPoint("TOPLEFT", trailSizeEndSlider, "BOTTOMLEFT", 0, -30)

    local trailLayerCountSlider = CreateSlider("TrailLayerCountSlider", menu, "Trail Layer Count", 1, 50, 1,
        EasyCursorTrailsDB.trailLayerCount or defaults.trailLayerCount,
        function(slider, value)
            EasyCursorTrailsDB.trailLayerCount = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Layer Count: %d", value)
            RebuildTrails()
        end
    )
    trailLayerCountSlider:SetPoint("TOPLEFT", trailCountSlider, "BOTTOMLEFT", 0, -30)

    local trailLayerSpacingSlider = CreateSlider("TrailLayerSpacingSlider", menu, "Trail Layer Spacing", 0, 50, 1,
        EasyCursorTrailsDB.trailLayerSpacing or defaults.trailLayerSpacing,
        function(slider, value)
            EasyCursorTrailsDB.trailLayerSpacing = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Layer Spacing: %d", value)
            -- Any additional logic if necessary
        end
    )
    trailLayerSpacingSlider:SetPoint("TOPLEFT", trailLayerCountSlider, "BOTTOMLEFT", 0, -30)

    local trailInitialSeparationSlider = CreateSlider("TrailInitialSeparationSlider", menu, "Trail Initial Separation", 0, 50, 1,
        EasyCursorTrailsDB.trailInitialSeparation or defaults.trailInitialSeparation,
        function(slider, value)
            EasyCursorTrailsDB.trailInitialSeparation = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Trail Initial Separation: %d", value)
            -- Any additional logic if necessary
        end
    )
    trailInitialSeparationSlider:SetPoint("TOPLEFT", trailLayerSpacingSlider, "BOTTOMLEFT", 0, -30)

    -- Offsets
    local trailOffsetSettingsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    trailOffsetSettingsHeader:SetPoint("TOPLEFT", trailInitialSeparationSlider, "BOTTOMLEFT", 0, -40)
    trailOffsetSettingsHeader:SetText("Trail Offset Settings")

    local trailOffsetXSlider = CreateSlider("TrailOffsetXSlider", menu, "Trail Offset X", -100, 100, 1,
    EasyCursorTrailsDB.trailOffsetX or defaults.trailOffsetX,
    function(slider, value)
        EasyCursorTrailsDB.trailOffsetX = value
        slider:SetValue(value)
        slider.text:SetFormattedText("Trail Offset X: %d", value)
        EasyCursorTrails.UpdateTrailOffsets()
    end
)
trailOffsetXSlider:SetPoint("TOPLEFT", trailOffsetSettingsHeader, "BOTTOMLEFT", 0, -30)

local trailOffsetYSlider = CreateSlider("TrailOffsetYSlider", menu, "Trail Offset Y", -100, 100, 1,
EasyCursorTrailsDB.trailOffsetY or defaults.trailOffsetY,
function(slider, value)
    EasyCursorTrailsDB.trailOffsetY = value
    slider:SetValue(value)
    slider.text:SetFormattedText("Trail Offset Y: %d", value)
    EasyCursorTrails.UpdateTrailOffsets()
end
)
trailOffsetYSlider:SetPoint("TOPLEFT", trailOffsetXSlider, "BOTTOMLEFT", 0, -30)


    
-------------------------------
    -- Effects Settings Section
    -------------------------------
    local effectsSettingsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    effectsSettingsHeader:SetPoint("TOPLEFT", trailOffsetYSlider, "BOTTOMLEFT", 0, -40)
    effectsSettingsHeader:SetText("Effects Settings")

    
 

        -- Dropdown: Select Trail Movement Effect
        local trailMovementEffectDropdown = CreateSimpleDropdown("TrailMovementEffectDropdown", menu, "Trail Movement Effect", trailMovementEffectOptions, EasyCursorTrailsDB.trailMovementEffect or 1, function(index)
            EasyCursorTrailsDB.trailMovementEffect = index
            EasyCursorTrailsDB.trailTexture = 1
            RebuildTrails()
            -- Re-apply cursor glow logic so it doesn't hide:
            EasyCursorTrails.ApplySelectedGlowEffect()
        end)
        
        trailMovementEffectDropdown:SetPoint("TOPLEFT", effectsSettingsHeader, "BOTTOMLEFT", -50, -10)
    
       
    -- Trail Movement Effect Dropdown
    local trailMovementEffectOptions = {}
    for i, effectName in ipairs(trailEffects) do
        table.insert(trailMovementEffectOptions, { text = effectName })
    end

    local trailMovementEffectDropdown = CreateSimpleDropdown("TrailMovementEffectDropdown", menu, "Trail Movement Effect", trailMovementEffectOptions, EasyCursorTrailsDB.trailMovementEffect or 1, function(index)
        EasyCursorTrailsDB.trailMovementEffect = index
        EasyCursorTrailsDB.trailTexture = 1
        RebuildTrails()
        UpdateTrailTextureDropdown(index)
    end)
    trailMovementEffectDropdown:SetPoint("TOPLEFT", effectsSettingsHeader, "BOTTOMLEFT", -50, -45)

    

    -- Trail Textures Dropdown
    local trailTextureDropdown = CreateDropdown("TrailTextureDropdown", menu, "Trail Textures", {}, EasyCursorTrailsDB.trailTexture or 1, function(index)
        EasyCursorTrailsDB.trailTexture = index
        RebuildTrails()
        -- Keep cursor glow frames updated:
        EasyCursorTrails.ApplySelectedGlowEffect()
    end)
    
    trailTextureDropdown:SetPoint("TOPLEFT", trailMovementEffectDropdown, "BOTTOMLEFT", 0, 0)

    
   function UpdateTrailTextureDropdown(selectedEffectIndex)
        local textureOptions = {}
        local textures = EasyCursorTrails.trailTextures[selectedEffectIndex]
        if textures then
            for i, textureInfo in ipairs(textures) do
                table.insert(textureOptions, { text = textureInfo.name, icon = textureInfo.texture })
            end
        else
            table.insert(textureOptions, { text = "No Textures Available", icon = nil })
        end

        UIDropDownMenu_Initialize(trailTextureDropdown, function(self, level, menuList)
            for i, option in ipairs(textureOptions) do
                local info = UIDropDownMenu_CreateInfo()
                info.text = option.text
                if option.icon then
                    info.icon = option.icon
                    info.iconTexCoord = {0,1,0,1}
                    info.iconWidth = 16
                    info.iconHeight = 16
                end
                info.func = function()
                    UIDropDownMenu_SetSelectedID(trailTextureDropdown, i)
                    UIDropDownMenu_SetText(trailTextureDropdown, option.text)
                    EasyCursorTrailsDB.trailTexture = i
                    RebuildTrails()
                    CloseDropDownMenus()
                end
                UIDropDownMenu_AddButton(info)
            end
        end)

        local currentTextureIndex = EasyCursorTrailsDB.trailTexture or 1
        if textureOptions[currentTextureIndex] then
            UIDropDownMenu_SetText(trailTextureDropdown, textureOptions[currentTextureIndex].text)
        else
            UIDropDownMenu_SetText(trailTextureDropdown, "Select a texture")
        end
    end
    UpdateTrailTextureDropdown(EasyCursorTrailsDB.trailMovementEffect or 1)

    -- Cursor Texture Dropdown
    local cursorTextureOptions = {}
    for i, cursorData in ipairs(customCursorTextures) do
        local displayName = cursorData.name
        if cursorData.animated then
            displayName = displayName .. " (Animated)"
        end
        table.insert(cursorTextureOptions, { text = displayName, icon = cursorData.texture })
    end

    local cursorTextureDropdown = CreateDropdown("CursorTextureDropdown", menu, "Cursor Textures", cursorTextureOptions,
        EasyCursorTrailsDB.cursorTexture or 1,
        function(index)
            EasyCursorTrailsDB.cursorTexture = index
            EasyCursorTrails.InitializeCustomCursor()
        end
    )
    cursorTextureDropdown:SetPoint("TOPLEFT", trailTextureDropdown, "BOTTOMLEFT", -320, 45)

    -- Cursor Color Effects Dropdown
    local cursorColorEffectOptions = {}
    for i, effect in ipairs(colorEffects) do
        table.insert(cursorColorEffectOptions, { text = effect.text })
    end

    local cursorColorEffectDropdown = CreateSimpleDropdown("CursorColorEffectDropdown", menu, "Cursor Color Effects",
        cursorColorEffectOptions,
        EasyCursorTrailsDB.cursorColorEffect or 1,
        function(index)
            EasyCursorTrailsDB.cursorColorEffect = index
            EasyCursorTrails.ApplyColorEffectCursor()
        end
    )
    cursorColorEffectDropdown:SetPoint("TOPLEFT", cursorTextureDropdown, "BOTTOMLEFT", 0, 0)

    -- Select Cursor Color Button
    local selectCursorColorButton = CreateFrame("Button", "SelectCursorColorButton", menu, "UIPanelButtonTemplate")
    selectCursorColorButton:SetSize(150, 25)
    selectCursorColorButton:SetText("Select Cursor Color")
    selectCursorColorButton:SetPoint("TOPLEFT", cursorColorEffectDropdown, "BOTTOMLEFT", 20, 0)
    selectCursorColorButton:SetScript("OnClick", function()
        local initialColor = EasyCursorTrailsDB.cursorColor or { r = 1, g = 1, b = 1, a = 1 }
        EasyCursorTrails.OpenColorPicker(initialColor, function(color)
            EasyCursorTrailsDB.cursorColor = color
            print("EasyCursorTrails: Selected Cursor Color =>", color.r, color.g, color.b, color.a)
            EasyCursorTrails.ApplyColorEffectCursor()
        end)
    end)

    -- Trail Color Effects Dropdown
    local trailColorEffectDropdown = CreateSimpleDropdown("TrailColorEffectDropdown", menu, "Trail Color Effects",
        TrailcolorEffects,
        EasyCursorTrailsDB.trailColorEffect or 1,
        function(index)
            EasyCursorTrailsDB.trailColorEffect = index
            local selectedEffectText = TrailcolorEffects[index] and TrailcolorEffects[index].text or "Unknown"
            print("EasyCursorTrails: Trail Color Effect set to", selectedEffectText)

            if EasyCursorTrails.trailPool and next(EasyCursorTrails.trailPool) ~= nil then
                for layer, trails in pairs(EasyCursorTrails.trailPool) do
                    if type(trails) == "table" then
                        for trailIndex, trail in ipairs(trails) do
                            if trail and trail.texture then
                                EasyCursorTrails.ApplyColorEffectTrail(trail, trailIndex)
                            end
                        end
                    end
                end
            else
                print("EasyCursorTrails Error: trailPool is nil or empty.")
            end
        end
    )
    trailColorEffectDropdown:SetPoint("TOPLEFT", trailMovementEffectDropdown, "BOTTOMLEFT", 0, -35)

    -- Select Trail Color Button
    local selectTrailColorButton = CreateFrame("Button", "SelectTrailColorButton", menu, "UIPanelButtonTemplate")
    selectTrailColorButton:SetSize(150, 25)
    selectTrailColorButton:SetText("Select Trail Color")
    selectTrailColorButton:SetPoint("TOPLEFT", trailColorEffectDropdown, "BOTTOMLEFT", 20, 0)
    selectTrailColorButton:SetScript("OnClick", function()
        local initialColor = EasyCursorTrailsDB.trailColor or { r = 1, g = 1, b = 1, a = 1 }
        EasyCursorTrails.OpenColorPicker(initialColor, function(color)
            EasyCursorTrailsDB.trailColor = color
            print(string.format("EasyCursorTrails: Selected Trail Color => R=%.2f, G=%.2f, B=%.2f, A=%.2f",
                color.r, color.g, color.b, color.a))
            if EasyCursorTrails.trailPool then
                for _, layerPool in pairs(EasyCursorTrails.trailPool) do
                    for _, trail in ipairs(layerPool) do
                        if trail and trail.texture then
                            EasyCursorTrails.ApplyColorEffectTrail(trail)
                        end
                    end
                end
            end
        end)
    end)

    -- Glow Settings Header
    local glowSettingsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    glowSettingsHeader:SetPoint("TOPLEFT", glowEffectDropdown, "BOTTOMLEFT", 0, -20)
    glowSettingsHeader:SetText("Glow Settings")


    -- Number of Glows Slider
    local numGlowsSlider = CreateSlider("NumGlowsSlider", menu, "Number of Glows", 0, 30, 1,
        EasyCursorTrailsDB.numGlows or 30,
        function(slider, value)
            value = math.floor(value)
            EasyCursorTrailsDB.numGlows = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Number of Glows: %d", value)
            EasyCursorTrails.UpdateGlowFrames()
        end
    )
    numGlowsSlider:SetPoint("TOPLEFT", trailCountSlider, "BOTTOMLEFT", -300, -30)

    -- Pattern Glow Count Slider
    local patternGlowCountSlider = CreateSlider(
        "PatternGlowCountSlider",
        menu,
        "Pattern Glow Count",
        3,
        29,
        1,
        EasyCursorTrailsDB.patternGlowCount or defaults.patternGlowCount,
        function(slider, value)
            value = math.floor(value)
            EasyCursorTrailsDB.patternGlowCount = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Pattern Glow Count: %d", value)
            print("EasyCursorTrails: Pattern Glow Count set to", value)
            EasyCursorTrails.UpdateGlowFrames()
        end
    )
    patternGlowCountSlider:SetPoint("TOPLEFT", numGlowsSlider, "BOTTOMLEFT", 0, -30)

    -- Glow Intensity Slider
    local glowIntensitySlider = CreateSlider(
        "GlowIntensitySlider",
        menu,
        "Glow Intensity",
        0.1,
        1.0,
        0.05,
        EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity,
        function(slider, value)
            value = math.max(0.1, math.min(1.0, value))
            EasyCursorTrailsDB.glowIntensity = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Glow Intensity: %.2f", value)
            EasyCursorTrails.ApplySelectedGlowEffect()
        end
    )
    glowIntensitySlider:SetPoint("TOPLEFT", patternGlowCountSlider, "BOTTOMLEFT", 0, -30)

-- Conceptual Example for a Continuous Glow Radius Slider
local glowRadiusSlider = CreateSlider("GlowRadiusSlider", menu, "Glow Radius", 0.1, 1.1, 0.01,
    EasyCursorTrailsDB.glowRadius or defaults.glowRadius,
    function(slider, value)
        EasyCursorTrailsDB.glowRadius = value
        slider.text:SetFormattedText("Glow Radius: %.2f", value)
        print(string.format("Debug: Glow Radius set to %.2f", value))
        EasyCursorTrails.UpdateGlowFrames()
    end
)
glowRadiusSlider:SetPoint("TOPLEFT", glowIntensitySlider, "BOTTOMLEFT", 0, -30)

-- Modify the CreateSlider function to allow non-discrete steps if necessary

    -- Glow Size Slider
    local glowSizeSlider = CreateSlider("GlowSizeSlider", menu, "Glow Size", 0.5, 1.0, 0.1,
        EasyCursorTrailsDB.glowSize or defaults.glowSize,
        function(slider, value)
            EasyCursorTrailsDB.glowSize = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Glow Size: %.1f", value)
            EasyCursorTrails.UpdateGlowFrames()
        end
    )
    glowSizeSlider:SetPoint("TOPLEFT", glowRadiusSlider, "BOTTOMLEFT", 0, -30)

    -- Glow Thickness Slider
    local glowThicknessSlider = CreateSlider("GlowThicknessSlider", menu, "Glow Thickness", 0.1, 2.0, 0.1,
        EasyCursorTrailsDB.glowThickness or defaults.glowThickness,
        function(slider, value)
            EasyCursorTrailsDB.glowThickness = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Glow Thickness: %.1f", value)
            EasyCursorTrails.UpdateGlowFrames()
        end
    )
    glowThicknessSlider:SetPoint("TOPLEFT", glowSizeSlider, "BOTTOMLEFT", 0, -30)

    -- Cursor Settings Header
    local cursorSettingsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    cursorSettingsHeader:SetPoint("TOPLEFT", menuTitle, "TOPLEFT", -100, -35)
    cursorSettingsHeader:SetText("Custom Cursor Settings")

    -- Cursor Size Slider
    local cursorSizeSlider = CreateSlider("CursorSizeSlider", menu, "Cursor Size", 10, 200, 1,
        EasyCursorTrailsDB.cursorSize or defaults.cursorSize,
        function(slider, value)
            EasyCursorTrailsDB.cursorSize = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Cursor Size: %d", value)
            EasyCursorTrails.UpdateCustomCursorSize(value)
            RebuildTrails()
        end
    )
    cursorSizeSlider:SetPoint("TOPLEFT", cursorSettingsHeader, "BOTTOMLEFT", 0, -80)

    -- Cursor Offset X Slider
    local cursorOffsetXSlider = CreateSlider("CursorOffsetXSlider", menu, "Cursor Offset X", -100, 100, 1,
        EasyCursorTrailsDB.cursorOffsetX or defaults.cursorOffsetX,
        function(slider, value)
            EasyCursorTrailsDB.cursorOffsetX = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Cursor Offset X: %d", value)
            EasyCursorTrails.UpdateCustomCursorPosition()
        end
    )
    cursorOffsetXSlider:SetPoint("TOPLEFT", cursorSizeSlider, "BOTTOMLEFT", 0, -30)

    -- Cursor Offset Y Slider
    local cursorOffsetYSlider = CreateSlider("CursorOffsetYSlider", menu, "Cursor Offset Y", -100, 100, 1,
        EasyCursorTrailsDB.cursorOffsetY or defaults.cursorOffsetY,
        function(slider, value)
            EasyCursorTrailsDB.cursorOffsetY = value
            slider:SetValue(value)
            slider.text:SetFormattedText("Cursor Offset Y: %d", value)
            EasyCursorTrails.UpdateCustomCursorPosition()
        end
    )
    cursorOffsetYSlider:SetPoint("TOPLEFT", cursorOffsetXSlider, "BOTTOMLEFT", 0, -30)

    -- Select Glow Color Button
    local selectGlowColorButton = CreateFrame("Button", "SelectGlowColorButton", menu, "UIPanelButtonTemplate")
    selectGlowColorButton:SetSize(150, 25)
    selectGlowColorButton:SetText("Select Glow Color")
    selectGlowColorButton:SetPoint("TOPLEFT", glowThicknessSlider, "BOTTOMLEFT", -50, -60)
    selectGlowColorButton:SetScript("OnClick", function()
        local initialColor = EasyCursorTrailsDB.glowColor or { r = 1, g = 1, b = 1, a = 1 }
        EasyCursorTrails.OpenColorPicker(initialColor, function(color)
            EasyCursorTrailsDB.glowColor = color
            print("EasyCursorTrails: Selected Glow Color =>", color.r, color.g, color.b, color.a)
            EasyCursorTrails.ApplySelectedGlowEffect()
        end)
    end)

    -- Glow Effect Dropdown
    EasyCursorTrails.glowEffectOptions = {
        { text = "None" },
        { text = "Normal Pulse" },
        { text = "Pulse like a star in the sky" },
        { text = "Pulse in clockwise direction" },
        { text = "Different random color in clockwise direction" },
        { text = "Pulse in anticlockwise direction" },
        { text = "Different random color in anticlockwise direction" },
        { text = "Disco light" },
        { text = "Wave pattern" },
        { text = "Airport trailing lights pattern" },
        { text = "Fast pulsing" },
        { text = "Slow pulsing" },
        { text = "Stretch Segments" },
        { text = "Burning" },
        { text = "Lightning" },
        { text = "Tinker Bell" },
        { text = "Random" },
    }

    local glowEffectDropdown = CreateSimpleDropdown("GlowEffectDropdown", menu, "Glow Effects",
        EasyCursorTrails.glowEffectOptions, EasyCursorTrailsDB.selectedGlowEffect or 1,
        function(index)
            EasyCursorTrailsDB.selectedGlowEffect = index
            print("EasyCursorTrails: Glow Effect set to", EasyCursorTrails.glowEffectOptions[index].text)
            EasyCursorTrails.ApplySelectedGlowEffect()
        end
    )
    glowEffectDropdown:SetPoint("TOPLEFT", selectGlowColorButton, "BOTTOMLEFT", -20, 60)

    -------------------------------
    -- Actions Section
    -------------------------------
    local actionsHeader = menu:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    actionsHeader:SetPoint("TOPLEFT",  selectGlowColorButton, "BOTTOMLEFT", 240, -180)
    actionsHeader:SetText("Actions")

    local frameStrataOptions = {
        { text = "BACKGROUND" },
        { text = "LOW" },
        { text = "MEDIUM" },
        { text = "HIGH" },
        { text = "DIALOG" },
    }

    local function GetStrataIndex(strata)
        for i, v in ipairs(frameStrataOptions) do
            if v.text == strata then
                return i
            end
        end
        return 4 -- Default to "HIGH"
    end

    local initialFrameStrataIndex = GetStrataIndex(EasyCursorTrailsDB.cursorFrameStrata) or 4

    local cursorFrameStrataDropdown = CreateDropdown("CursorFrameStrataDropdown", menu, "Cursor Frame Strata", frameStrataOptions, initialFrameStrataIndex, function(selectedIndex)
        EasyCursorTrailsDB.cursorFrameStrata = frameStrataOptions[selectedIndex].text
        if customCursor then
            customCursor:SetFrameStrata(frameStrataOptions[selectedIndex].text)
            print("EasyCursorTrails: Cursor Frame Strata set to", frameStrataOptions[selectedIndex].text)
        end
    end)
    cursorFrameStrataDropdown:SetPoint("TOPLEFT", glowEffectDropdown, "BOTTOMLEFT", 0, -35)


    -- OK and Close Buttons
    local okButton = CreateFrame("Button", "OkButton", menu, "UIPanelButtonTemplate")
    okButton:SetSize(100, 25)
    okButton:SetText("OK")
    okButton:SetPoint("TOPLEFT", actionsHeader, "BOTTOMLEFT", -95, -20)
    okButton:SetScript("OnClick", function()
        RebuildTrails()
        print("EasyCursorTrails: Trail settings saved!")
    end)

    local closeButton = CreateFrame("Button", "CloseButton", menu, "UIPanelButtonTemplate")
    closeButton:SetSize(100, 25)
    closeButton:SetText("Close")
    closeButton:SetPoint("LEFT", okButton, "RIGHT", 50, 0)
    closeButton:SetScript("OnClick", function()
        menu:Hide()
        print("EasyCursorTrails: Settings closed.")
    end)

    
    -------------------------------
    -- Minimap Button
    -------------------------------
    local minimapButton = CreateFrame("Button", "EasyCursorTrailsMinimapButton", Minimap)
    minimapButton:SetSize(32, 32)
    minimapButton:SetNormalTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\icon.tga")
    minimapButton:SetHighlightTexture("Interface\\Buttons\\UI-Minimap-ZoomButton-Highlight.blp")
    minimapButton:SetPoint("TOPLEFT", Minimap, "TOPLEFT", -10, -10)
    minimapButton:SetScript("OnClick", function()
        menu:SetShown(not menu:IsShown())
    end)

    minimapButton:SetScript("OnEnter", function(self)
        GameTooltip:SetOwner(self, "ANCHOR_RIGHT")
        GameTooltip:AddLine("Easy Cursor Trails")
        GameTooltip:AddLine("Click to open the settings menu.", 1, 1, 1)
        GameTooltip:Show()
    end)
    minimapButton:SetScript("OnLeave", function()
        GameTooltip:Hide()
    end)



    RebuildTrails()
end


--------------------------------------------------------
-- Animations for Glow
--------------------------------------------------------
local function CreatePulsingAnimation(animationGroup, color, intensity, duration, startDelay)
    if not animationGroup or not animationGroup.CreateAnimation then
        print("EasyCursorTrails: Invalid AnimationGroup in CreatePulsingAnimation.")
        return
    end
    startDelay = startDelay or 0

    local alphaAnim1 = animationGroup:CreateAnimation("Alpha")
    alphaAnim1:SetFromAlpha(color.a * intensity)
    alphaAnim1:SetToAlpha(color.a * intensity * 9.5)
    alphaAnim1:SetDuration(duration / 2)
    alphaAnim1:SetStartDelay(startDelay)
    alphaAnim1:SetOrder(1)

    local alphaAnim2 = animationGroup:CreateAnimation("Alpha")
    alphaAnim2:SetFromAlpha(color.a * intensity * 0.1)
    alphaAnim2:SetToAlpha(color.a * intensity)
    alphaAnim2:SetDuration(duration / 2)
    alphaAnim2:SetOrder(2)

    animationGroup:SetLooping("REPEAT")
    animationGroup:Play()
end

function EasyCursorTrails.ApplyDefaultCircularGlow()
    print("EasyCursorTrails: Applying default circular glow.")

    local NUM_GLOWS = #customCursor.glowEffects
    if NUM_GLOWS < 1 then return end

    local angleStep = 360 / NUM_GLOWS
    local cursorRadius = customCursor:GetWidth() / 1.5
    local rad = EasyCursorTrailsDB.glowRadius or defaults.glowRadius
    local offsetDistance = cursorRadius * rad

    for i, glow in ipairs(customCursor.glowEffects) do
        if glow and glow.texture then
            local angle = math.rad((i - 1) * angleStep)
            local offsetX = math.cos(angle) * offsetDistance
            local offsetY = math.sin(angle) * offsetDistance

            glow:SetPoint("CENTER", customCursor, "CENTER", offsetX, offsetY)
            local size = (customCursor:GetWidth() * (EasyCursorTrailsDB.glowSize or defaults.glowSize))
                        * (EasyCursorTrailsDB.glowThickness or defaults.glowThickness)
            glow:SetSize(size, size)
            glow.texture:SetVertexColor(EasyCursorTrailsDB.glowColor.r,
                                        EasyCursorTrailsDB.glowColor.g,
                                        EasyCursorTrailsDB.glowColor.b)
            glow.texture:SetAlpha(EasyCursorTrailsDB.glowIntensity * EasyCursorTrailsDB.glowColor.a)
            glow:Show()
        end
    end
end

function EasyCursorTrails.ApplySelectedGlowEffect()
    -- 1) Basic safety checks
    if not customCursor or not customCursor.glowEffects then
        print("EasyCursorTrails: customCursor or glowEffects not initialized.")
        return
    end

    local glowEffectOptions = EasyCursorTrails.glowEffectOptions
    if not glowEffectOptions then
        print("EasyCursorTrails: glowEffectOptions is missing or nil.")
        return
    end


    -- 2) Determine which effect is selected
    local selectedEffect = EasyCursorTrailsDB.selectedGlowEffect or 1
    local totalEffects   = #glowEffectOptions

    -- 3) If "Random" => pick a random effect
    if glowEffectOptions[selectedEffect]
       and glowEffectOptions[selectedEffect].text == "Random" then
        selectedEffect = math.random(1, totalEffects - 1)
        EasyCursorTrailsDB.selectedGlowEffect = selectedEffect
    end

    -- 4) Obtain the short name for the current cursor
    local currentCursorTexture = EasyCursorTrailsDB.selectedCursorTextureName
    if not currentCursorTexture or currentCursorTexture == "" then
        print("EasyCursorTrails: No currentCursorTexture => fallback to default circle.")
        EasyCursorTrails.ApplyDefaultCircularGlow()
        return
    end

    -- 5) Check if we have a pattern for that short name
    local patternName = EasyCursorTrails.cursorGlowMapping[currentCursorTexture]
    if not patternName then
        print("EasyCursorTrails: No pattern mapping for", currentCursorTexture, "=> fallback to default circle.")
        EasyCursorTrails.ApplyDefaultCircularGlow()
        return
    end

    local glowPattern = EasyCursorTrails.glowPatterns[patternName]
    if not glowPattern then
        print("EasyCursorTrails: Glow pattern '"..patternName.."' not defined => fallback to default circle.")
        EasyCursorTrails.ApplyDefaultCircularGlow()
        return
    end

    -- 6) Grab color & user-chosen radius
     -- 6) Grab color & user-chosen radius
    local glowColor  = EasyCursorTrailsDB.glowColor or { r = 1, g = 1, b = 1, a = 1 }
    local intensity  = EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity
    local glowRadius = tonumber(EasyCursorTrailsDB.glowRadius) or defaults.glowRadius -- Ensure it's a number
    print("Debug: glowRadius type:", type(glowRadius), "value:", glowRadius)
    local cursorWidth = customCursor:GetWidth() or 64
    local radiusScale = glowRadius * (cursorWidth / 5.5)

    -- 7) Generate coordinates based on the pattern
    local coords = nil
    if type(glowPattern) == "function" then
        local count = EasyCursorTrailsDB.patternGlowCount or 8
        coords = glowPattern(count)
    elseif type(glowPattern) == "table" then
        coords = glowPattern
    end

    -- 8) Position each glow frame
    for i, glow in ipairs(customCursor.glowEffects) do
        if glow and glow.texture then
            -- STOP & DISCARD the old AnimationGroup
            if glow.animationGroup then
                glow.animationGroup:Stop()
                -- Discard the old group by creating a new one
                glow.animationGroup = glow:CreateAnimationGroup()
            else
                -- If no animationGroup exists, create one
                glow.animationGroup = glow:CreateAnimationGroup()
            end

            glow.texture:SetBlendMode("ADD")
            glow.texture:SetVertexColor(glowColor.r, glowColor.g, glowColor.b, glowColor.a * intensity)

            if coords and coords[i] then
                local x = coords[i].x
                local y = coords[i].y
                local offsetX = x * radiusScale
                local offsetY = y * radiusScale
                glow:ClearAllPoints()
                glow:SetPoint("CENTER", customCursor, "CENTER", offsetX, offsetY)
                glow:Show()
            else
                glow:Hide()
            end

            -- Scale the glow frame
            local size = (cursorWidth * (EasyCursorTrailsDB.glowSize or defaults.glowSize)) *
                         (EasyCursorTrailsDB.glowThickness or defaults.glowThickness)
            glow:SetSize(size, size)

            -- 9) Apply the selected glow effect
            if selectedEffect == 1 then
                -- None
                glow.texture:SetVertexColor(glowColor.r, glowColor.g, glowColor.b, glowColor.a * 0.2)
                glow.texture:SetAlpha(glowColor.a * 0.2)

            elseif selectedEffect == 2 then
                -- Normal Pulse
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 1.0)

            elseif selectedEffect == 3 then
                -- Pulse like a star
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 0.8)

            elseif selectedEffect == 4 then
                -- Pulse clockwise w/ staggered start
                local delay = (i - 1) * 0.05
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 1.0, delay)

            elseif selectedEffect == 5 then
                -- Different random color, clockwise
                local r, g, b = math.random(), math.random(), math.random()
                glow.texture:SetVertexColor(r, g, b, glowColor.a * intensity)
                local delay = (i - 1) * 0.05
                CreatePulsingAnimation(
                    glow.animationGroup,
                    { r = r, g = g, b = b, a = glowColor.a },
                    intensity,
                    1.0,
                    delay
                )

            elseif selectedEffect == 6 then
                -- Pulse anticlockwise
                local delay = (#customCursor.glowEffects - i) * 0.05
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 1.0, delay)

            elseif selectedEffect == 7 then
                -- Different random color, anticlockwise
                local r, g, b = math.random(), math.random(), math.random()
                glow.texture:SetVertexColor(r, g, b, glowColor.a * intensity)
                local delay = (#customCursor.glowEffects - i) * 0.05
                CreatePulsingAnimation(
                    glow.animationGroup,
                    { r = r, g = g, b = b, a = glowColor.a },
                    intensity,
                    1.0,
                    delay
                )

            elseif selectedEffect == 8 then
                -- Disco light
                local r, g, b = math.random(), math.random(), math.random()
                glow.texture:SetVertexColor(r, g, b, glowColor.a * intensity)
                CreatePulsingAnimation(
                    glow.animationGroup,
                    { r = r, g = g, b = b, a = glowColor.a },
                    intensity,
                    0.3
                )

            elseif selectedEffect == 9 then
                -- Wave pattern
                local delay = (i - 1) * 0.1
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 1.0, delay)

            elseif selectedEffect == 10 then
                -- Airport trailing lights
                if i % 2 == 0 then
                    CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 0.2)
                else
                    CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 0.2, 0.1)
                end

            elseif selectedEffect == 11 then
                -- Fast pulsing
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 0.1)

            elseif selectedEffect == 12 then
                -- Slow pulsing
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, 2.0)

            elseif selectedEffect == 13 then
                -- Stretch Segments
                local stretchAnim = glow.animationGroup:CreateAnimation("Scale")
                stretchAnim:SetScale(1.2, 1.2)
                stretchAnim:SetDuration(0.3)
                stretchAnim:SetOrder(1)

                local contractAnim = glow.animationGroup:CreateAnimation("Scale")
                contractAnim:SetScale(0.8, 0.8)
                contractAnim:SetDuration(0.3)
                contractAnim:SetOrder(2)

                glow.animationGroup:SetLooping("REPEAT")
                glow.animationGroup:Play()

            elseif selectedEffect == 14 then
                -- Burning Flicker
                glow.texture:SetVertexColor(1, 0.5, 0, glowColor.a * intensity)
                CreatePulsingAnimation(
                    glow.animationGroup,
                    { r = 1, g = 0.5, b = 0, a = glowColor.a },
                    intensity,
                    0.5,
                    0.1
                )

            elseif selectedEffect == 15 then
                -- Lightning
                local lightningAnim = glow.animationGroup:CreateAnimation("Alpha")
                lightningAnim:SetFromAlpha(0)
                lightningAnim:SetToAlpha(glowColor.a * intensity)
                lightningAnim:SetDuration(0.1)
                lightningAnim:SetStartDelay(0.2)
                lightningAnim:SetOrder(1)

                local fadeOutAnim = glow.animationGroup:CreateAnimation("Alpha")
                fadeOutAnim:SetFromAlpha(glowColor.a * intensity)
                fadeOutAnim:SetToAlpha(0)
                fadeOutAnim:SetDuration(0.2)
                fadeOutAnim:SetOrder(2)

                local scaleAnim = glow.animationGroup:CreateAnimation("Scale")
                scaleAnim:SetScale(1.0, 2.0)
                scaleAnim:SetDuration(0.3)
                scaleAnim:SetOrder(3)

                glow.animationGroup:SetLooping("REPEAT")
                glow.animationGroup:Play()

            elseif selectedEffect == 16 then
                -- Tinker Bell
                glow.texture:SetVertexColor(1, 0.84, 0, glowColor.a * intensity)
                local pulseDuration = 0.4 + math.random() * 0.2
                CreatePulsingAnimation(glow.animationGroup, glowColor, intensity, pulseDuration)

            else
                -- Default / fallback
                glow.texture:SetVertexColor(glowColor.r, glowColor.g, glowColor.b, glowColor.a * intensity)
                glow.texture:SetAlpha(glowColor.a * intensity)
            end
        end
    end
end


function EasyCursorTrails.InitializeGlowFrames()
    if not customCursor or not customCursor.texture then return end
    if not customCursor.glowEffects then
        customCursor.glowEffects = {}
    else
        for _, glow in ipairs(customCursor.glowEffects) do
            glow:Hide()
            glow:ClearAllPoints()
            glow:SetParent(nil)
        end
        customCursor.glowEffects = {}
    end

    local NUM_GLOWS = EasyCursorTrailsDB.numGlows or 20
    local cursorWidth  = customCursor:GetWidth()
    local userRadius   = EasyCursorTrailsDB.glowRadius or defaults.glowRadius
    local cursorRadius = cursorWidth / 1.5

    for i = 1, NUM_GLOWS do
        local glow = CreateFrame("Frame", nil, customCursor)
        glow:SetSize(16, 16)
        glow:SetFrameStrata("HIGH")
        glow:SetFrameLevel(customCursor:GetFrameLevel() + 5)

        glow.texture = glow:CreateTexture(nil, "OVERLAY")
        glow.texture:SetAllPoints(true)
        glow.texture:SetBlendMode("ADD")
        glow.texture:SetTexture("Interface\\GLUES\\MODELS\\UI_Draenei\\GenericGlow64")
        glow.texture:SetVertexColor(1,1,1,EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity)

        local angle = math.rad((i - 1)*(360/NUM_GLOWS))
        local offsetX = math.cos(angle)*cursorRadius*userRadius
        local offsetY = math.sin(angle)*cursorRadius*userRadius
        glow:SetPoint("CENTER", customCursor, "CENTER", offsetX, offsetY)
        table.insert(customCursor.glowEffects, glow)
    end
end

function EasyCursorTrails.UpdateGlowFrames()
    if not customCursor or not customCursor.texture then
        print("EasyCursorTrails: customCursor or its texture is not initialized.")
        return
    end

    local cursorWidth   = customCursor:GetWidth() or 64
    local glowRadius    = tonumber(EasyCursorTrailsDB.glowRadius)    or defaults.glowRadius
    local glowSize      = tonumber(EasyCursorTrailsDB.glowSize)      or defaults.glowSize
    local glowThickness = tonumber(EasyCursorTrailsDB.glowThickness) or defaults.glowThickness
    local numGlows      = math.max(0, math.min(tonumber(EasyCursorTrailsDB.numGlows) or 20, 30))

    local currentGlows = #customCursor.glowEffects
    if currentGlows > numGlows then
        for i = currentGlows, numGlows + 1, -1 do
            local glow = table.remove(customCursor.glowEffects, i)
            if glow then
                glow:Hide()
                glow:SetParent(nil)
                if glow.texture then
                    glow.texture:SetTexture(nil)
                end
            end
        end
    elseif currentGlows < numGlows then
        for i = currentGlows+1, numGlows do
            local glow = CreateFrame("Frame", nil, customCursor)
            glow:SetSize(16, 16)
            glow:SetFrameStrata("HIGH")
            glow:SetFrameLevel(customCursor:GetFrameLevel()+5)
            local tex = glow:CreateTexture(nil, "OVERLAY")
            tex:SetAllPoints(true)
            tex:SetBlendMode("ADD")
            tex:SetTexture("Interface\\GLUES\\MODELS\\UI_Draenei\\GenericGlow64")
            tex:SetVertexColor(1,1,1)
            glow.texture = tex
            glow:Hide()
            table.insert(customCursor.glowEffects, glow)
        end
    end

    local shortName  = EasyCursorTrailsDB.selectedCursorTextureName
    local patternKey = shortName and EasyCursorTrails.cursorGlowMapping[shortName] or nil
    local patternFunction = patternKey and EasyCursorTrails.dynamicPatterns[patternKey] or nil

    local cursorRadius = cursorWidth / 5.5
    local usedCoordsCount = 0
    local coords = nil

    if patternFunction then
        local patternCount = EasyCursorTrailsDB.patternGlowCount or defaults.patternGlowCount
        coords = patternFunction(patternCount)
        usedCoordsCount = coords and #coords or 0
    end

    if coords then
        for i, glow in ipairs(customCursor.glowEffects) do
            if coords[i] and i <= numGlows then
                local x = coords[i].x
                local y = coords[i].y
                local scaleFactor = (glowRadius * cursorRadius) / 20
                local offsetX = x * scaleFactor
                local offsetY = y * scaleFactor
                glow:ClearAllPoints()
                glow:SetPoint("CENTER", customCursor, "CENTER", offsetX, offsetY)
                local size = (cursorWidth * glowSize) * glowThickness
                glow:SetSize(size, size)
                local alpha = EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity
                glow.texture:SetAlpha(alpha)
                glow:Show()
            else
                glow:Hide()
            end
        end
    else
        -- fallback circle
        local angleStep = (numGlows>0) and (360/numGlows) or 0
        for i, glow in ipairs(customCursor.glowEffects) do
            if i<=numGlows and glow and glow.texture then
                local angle = math.rad((i - 1)*angleStep)
                local offsetDist = cursorRadius * glowRadius
                local offsetX = offsetDist * math.cos(angle)
                local offsetY = offsetDist * math.sin(angle)
                glow:ClearAllPoints()
                glow:SetPoint("CENTER", customCursor, "CENTER", offsetX, offsetY)
                local size = (cursorWidth * glowSize)*glowThickness
                glow:SetSize(size, size)
                local alpha = EasyCursorTrailsDB.glowIntensity or defaults.glowIntensity
                glow.texture:SetAlpha(alpha)
                glow:Show()
            else
                glow:Hide()
            end
        end
    end

    EasyCursorTrails.ApplySelectedGlowEffect()
    print(string.format(
        "EasyCursorTrails: Updated glow frames => %d total. Radius=%.1f, patternKey=%s, coordsUsed=%d",
        numGlows, glowRadius, patternKey or "None", usedCoordsCount
    ))
end

function EasyCursorTrails.InitializeCustomCursor()
    if not customCursor then
        customCursor = CreateFrame("Frame", "EasyCursorCustomCursor", UIParent, "BackdropTemplate")
        customCursor:SetPoint("CENTER", UIParent, "CENTER")
        customCursor:SetFrameStrata("MEDIUM")
        customCursor:EnableMouse(false)
    end

    local cursorSize = EasyCursorTrailsDB.cursorSize or 32
    customCursor:SetSize(cursorSize, cursorSize)

    if not customCursor.texture then
        customCursor.texture = customCursor:CreateTexture(nil, "OVERLAY")
        customCursor.texture:SetAllPoints()
        customCursor.texture:SetBlendMode("ADD")
    end

    local cursorIndex = EasyCursorTrailsDB.cursorTexture or 1
    local cursorData  = customCursorTextures[cursorIndex]

    if not cursorData then
        print("EasyCursorTrails: Invalid cursor data for index", cursorIndex)
        customCursor.texture:SetTexture("Interface\\CURSOR\\Arrow")
        customCursor:SetScript("OnUpdate", nil)
    else
        -- Save shortName for pattern mapping
        if cursorData.texture then
            local path = cursorData.texture
            local filename = path:match("([^/\\]+)$") or ""
            filename = filename:gsub("%.tga", ""):gsub("%.blp", "")
            EasyCursorTrailsDB.selectedCursorTextureName = filename
        elseif cursorData.textures and #cursorData.textures>0 then
            local path = cursorData.textures[1]
            local filename = path:match("([^/\\]+)$") or ""
            filename = filename:gsub("%.tga", ""):gsub("%.blp", "")
            EasyCursorTrailsDB.selectedCursorTextureName = filename
        else
            EasyCursorTrailsDB.selectedCursorTextureName = "Unknown"
        end

        if cursorData.animated then
            local totalFrames       = #cursorData.textures
            local animationDuration = cursorData.animationDuration or 1
            customCursor.texture:SetTexture(cursorData.textures[1] or "Interface\\CURSOR\\Arrow")
            customCursor.texture:SetTexCoord(0,1,0,1)
            customCursor:SetScript("OnUpdate", function(self, elapsed)
                self.elapsedTime = (self.elapsedTime or 0) + elapsed
                local frameIndex = math.floor(
                    (self.elapsedTime % animationDuration)/animationDuration*totalFrames
                ) + 1
                if frameIndex>totalFrames then
                    frameIndex=1
                    self.elapsedTime=0
                end
                self.texture:SetTexture(cursorData.textures[frameIndex] or "Interface\\CURSOR\\Arrow")
            end)
        else
            customCursor.texture:SetTexture(cursorData.texture or "Interface\\CURSOR\\Arrow")
            customCursor.texture:SetTexCoord(0,1,0,1)
            customCursor:SetScript("OnUpdate", nil)
        end
    end

    if not customCursor.glowEffects or #customCursor.glowEffects==0 then
        EasyCursorTrails.InitializeGlowFrames()
    end
    EasyCursorTrails.UpdateGlowFrames()
    EasyCursorTrails.ApplySelectedGlowEffect()
    customCursor:Show()
end

function EasyCursorTrails.UpdateCustomCursorPosition()
    if not customCursor then
        print("EasyCursorTrails: customCursor not initialized.")
        return
    end

    local xOffset = EasyCursorTrailsDB.cursorOffsetX or 0
    local yOffset = EasyCursorTrailsDB.cursorOffsetY or 0
    local x, y = GetCursorPosition()
    local scale = UIParent:GetEffectiveScale()
    x = x/scale + xOffset
    y = y/scale + yOffset
    customCursor:SetPoint("CENTER", UIParent, "BOTTOMLEFT", x, y)
end

function EasyCursorTrails.UpdateCustomCursorSize(size)
    if type(size) ~= "number" then
        EasyCursorTrails.HandleError("UpdateCustomCursorSize: 'size' is not a number. Received: " .. tostring(size))
        print("Debug: 'size' is of type " .. type(size))
        return
    end

    if customCursor then
        print(string.format("Debug: Setting customCursor size to %d", size))
        customCursor:SetSize(size, size)
        EasyCursorTrails.UpdateGlowFrames()
    end
end

function RebuildTrails()
    -- Ensure saved variables are set
    EasyCursorTrailsDB.trailSizeStart = tonumber(EasyCursorTrailsDB.trailSizeStart) or defaults.trailSizeStart
    EasyCursorTrailsDB.trailSizeEnd   = tonumber(EasyCursorTrailsDB.trailSizeEnd)   or defaults.trailSizeEnd
    EasyCursorTrailsDB.trailLayerCount = tonumber(EasyCursorTrailsDB.trailLayerCount) or defaults.trailLayerCount
    EasyCursorTrailsDB.trailCount     = tonumber(EasyCursorTrailsDB.trailCount)     or defaults.trailCount
    EasyCursorTrailsDB.trailFrameStrata = EasyCursorTrailsDB.trailFrameStrata or defaults.trailFrameStrata
    EasyCursorTrailsDB.trailMovementEffect = tonumber(EasyCursorTrailsDB.trailMovementEffect) or defaults.trailMovementEffect
    EasyCursorTrailsDB.trailTexture   = tonumber(EasyCursorTrailsDB.trailTexture)   or defaults.trailTexture

    -- Clean up existing trails
    if EasyCursorTrails.trailPool then
        for _, layerPool in pairs(EasyCursorTrails.trailPool) do
            for _, trail in ipairs(layerPool) do
                trail:Hide()
                trail:ClearAllPoints()
                trail:SetParent(nil)
            end
        end
    end
    EasyCursorTrails.trailPool = {}
    EasyCursorTrails.cursorPositions = {}

    -- Determine the frame strata for the trails
    local trailStrata = EasyCursorTrailsDB.trailFrameStrata or "TOOLTIP"

    -- Recreate trail frames
    for layer = 1, EasyCursorTrailsDB.trailLayerCount do
        EasyCursorTrails.trailPool[layer] = {}
        for i = 1, EasyCursorTrailsDB.trailCount do
            local size
            if EasyCursorTrailsDB.trailCount > 1 then
                size = EasyCursorTrailsDB.trailSizeStart + 
                    ((EasyCursorTrailsDB.trailSizeEnd - EasyCursorTrailsDB.trailSizeStart) * ((i - 1) / (EasyCursorTrailsDB.trailCount - 1)))
            else
                size = EasyCursorTrailsDB.trailSizeStart
            end

            local trailName = "EasyCursorTrail_" .. layer .. "_" .. i
            local trail = CreateFrame("Frame", trailName, UIParent, "BackdropTemplate")
            trail:SetSize(size, size)
            trail.originalSize = size
            trail:SetFrameStrata(trailStrata)
            trail:SetAlpha(1)
            trail:Hide()

            -- Create and set up the trail's texture
            trail.texture = trail:CreateTexture(nil, "BACKGROUND")
            trail.texture:SetAllPoints(true)

            local currentTrailEffect = EasyCursorTrailsDB.trailMovementEffect or 1
            local currentTrailTexture = EasyCursorTrailsDB.trailTexture or 1
            local effectTable = EasyCursorTrails.trailTextures[currentTrailEffect]
            local textureData = effectTable and effectTable[currentTrailTexture]

            if not textureData or not textureData.texture then
                trail.texture:SetTexture("Interface\\CURSOR\\Arrow") -- Default texture, replace as needed
                EasyCursorTrails.HandleError("Missing texture for Movement=" .. tostring(currentTrailEffect) .. " Texture=" .. tostring(currentTrailTexture))
            else
                trail.texture:SetTexture(textureData.texture)
            end

            -- Apply color effects to the trail
            EasyCursorTrails.ApplyColorEffectTrail(trail, i)
            print("Debug: Created trail " .. trailName .. " with texture " .. (textureData and textureData.texture or "None"))

            -- Add trail to the pool
            table.insert(EasyCursorTrails.trailPool[layer], trail)
        end
    end

    -- Update trail offsets to position the newly created trails
    if EasyCursorTrails.UpdateTrailOffsets then
        EasyCursorTrails.UpdateTrailOffsets()
        print("Debug: Called UpdateTrailOffsets after rebuilding trails.")
    else
        EasyCursorTrails.HandleError("RebuildTrails: UpdateTrailOffsets function is missing.")
    end

    print("EasyCursorTrails: Trails rebuilt successfully!")
end



EasyCursorTrails.previousCursorX = EasyCursorTrails.previousCursorX or nil
EasyCursorTrails.previousCursorY = EasyCursorTrails.previousCursorY or nil
EasyCursorTrails.cursorPositions = EasyCursorTrails.cursorPositions or {}
EasyCursorTrails.cursorStopped   = EasyCursorTrails.cursorStopped or false

-- Initialize essential variables
EasyCursorTrails.cursorPositions = {}
EasyCursorTrails.cursorStopped = false
EasyCursorTrails.previousCursorX = nil
EasyCursorTrails.previousCursorY = nil



-- Define the HandleTrailMovement function within EasyCursorTrails
function EasyCursorTrails.HandleTrailMovement(elapsed)
    -- Validate the existence of trailPool
    if not EasyCursorTrails.trailPool then
        return
    end

    -- Ensure saved variables are initialized
    EasyCursorTrailsDB = EasyCursorTrailsDB or {}

    -- Retrieve and validate spacing and separation settings
    local maximumOffset = tonumber(EasyCursorTrailsDB.trailLayerSpacing) or 30
    local initialSeparation = tonumber(EasyCursorTrailsDB.trailInitialSeparation) or 0

    -- Debugging statements
    print(string.format("Debug: maximumOffset type: %s, value: %s", type(maximumOffset), tostring(maximumOffset)))
    print(string.format("Debug: initialSeparation type: %s, value: %s", type(initialSeparation), tostring(initialSeparation)))

    -- Get current cursor position in UI coordinates
    local cursorX, cursorY = GetCursorPosition()
    local uiScale = UIParent:GetEffectiveScale()
    cursorX, cursorY = cursorX / uiScale, cursorY / uiScale

    -- Update custom cursor position and apply color effects
    EasyCursorTrails.UpdateCustomCursorPosition(0, 0)
    EasyCursorTrails.ApplyColorEffectCursor()

    if EasyCursorTrailsDB.enableTrails then
        local cursorMoved = false

        -- Initialize cursorPositions and cursorStopped if not already
        EasyCursorTrails.cursorPositions = EasyCursorTrails.cursorPositions or {}
        EasyCursorTrails.cursorStopped = EasyCursorTrails.cursorStopped or false

        if EasyCursorTrails.previousCursorX and EasyCursorTrails.previousCursorY then
            local dx = cursorX - EasyCursorTrails.previousCursorX
            local dy = cursorY - EasyCursorTrails.previousCursorY
            local distance = math.sqrt(dx^2 + dy^2)
            local movementThreshold = 0.1

            if distance >= movementThreshold then
                cursorMoved = true
                EasyCursorTrails.cursorStopped = false
                table.insert(EasyCursorTrails.cursorPositions, 1, { x = cursorX, y = cursorY })
                if #EasyCursorTrails.cursorPositions > (EasyCursorTrailsDB.trailCount + 1) then
                    table.remove(EasyCursorTrails.cursorPositions)
                end
            else
                if not EasyCursorTrails.cursorStopped then
                    EasyCursorTrails.cursorStopped = true
                end
            end
        else
            EasyCursorTrails.previousCursorX, EasyCursorTrails.previousCursorY = cursorX, cursorY
            table.insert(EasyCursorTrails.cursorPositions, 1, { x = cursorX, y = cursorY })
        end

        EasyCursorTrails.previousCursorX, EasyCursorTrails.previousCursorY = cursorX, cursorY

        for layer = 1, EasyCursorTrailsDB.trailLayerCount do
            local layerTrails = EasyCursorTrails.trailPool[layer]
            local layerDirection = 0
            if EasyCursorTrailsDB.trailLayerCount > 1 then
                layerDirection = ((layer - 1) / (EasyCursorTrailsDB.trailLayerCount - 1)) * math.pi * 2
            end

            for i = 1, EasyCursorTrailsDB.trailCount do
                local trail = layerTrails[i]
                if trail and EasyCursorTrails.cursorPositions[i] then
                    local pos = EasyCursorTrails.cursorPositions[i]
                    local nextPos = EasyCursorTrails.cursorPositions[i + 1]
                    if not trail.originalSize then
                        trail.originalSize = trail:GetWidth() or 32
                    end
                    local separationFactor = (i - 1) / math.max(EasyCursorTrailsDB.trailCount - 1, 1)
                    local offsetDistance = initialSeparation + separationFactor * (maximumOffset - initialSeparation)
                    local offsetX, offsetY = 0, 0
                    local movementEffect = EasyCursorTrailsDB.trailMovementEffect or 1

                    if movementEffect == 1 then
                        -- Linear Separation
                        offsetX = offsetDistance * math.cos(layerDirection)
                        offsetY = offsetDistance * math.sin(layerDirection)
                    elseif movementEffect == 2 then
                        -- Curling Effect
                        local curlAmount = separationFactor * math.pi * 4
                        offsetX = offsetDistance * math.cos(layerDirection + curlAmount)
                        offsetY = offsetDistance * math.sin(layerDirection + curlAmount)
                    elseif movementEffect == 3 then
                        -- Wave Effect
                        local waveAmplitude = maximumOffset
                        local waveFrequency = 2
                        offsetX = offsetDistance * math.cos(layerDirection)
                        offsetY = waveAmplitude * math.sin(separationFactor * math.pi * waveFrequency)
                    elseif movementEffect == 4 then
                        -- Flag Effect
                        local flagAmplitude = maximumOffset
                        local flagFrequency = 2
                        offsetX = separationFactor * maximumOffset
                        offsetY = flagAmplitude * math.sin(separationFactor * math.pi * flagFrequency)
                    elseif movementEffect == 5 then
                        -- Echo Effect
                        local echoOffset = initialSeparation * 0.2 -- 20% of initialSeparation for subtlety
                        offsetX = echoOffset * math.cos(layerDirection)
                        offsetY = echoOffset * math.sin(layerDirection)
                    elseif movementEffect == 6 then
                        -- Zig Zag Effect
                        local zigzagSize = maximumOffset
                        if math.floor(separationFactor * 10) % 2 == 0 then
                            offsetX = zigzagSize
                        else
                            offsetX = -zigzagSize
                        end
                        offsetY = -separationFactor * maximumOffset
                    elseif movementEffect == 7 then
                        -- Spiral Effect
                        local spiralTurns = 2 -- Number of spiral turns
                        local angle = separationFactor * spiralTurns * 2 * math.pi
                        offsetX = offsetDistance * math.cos(angle)
                        offsetY = offsetDistance * math.sin(angle)
                    elseif movementEffect == 8 then
                        -- Explosion Effect
                        local explosionFactor = 1.5 -- Adjust to control explosion intensity
                        local explosionOffset = separationFactor * (maximumOffset * explosionFactor)
                        offsetX = explosionOffset * math.cos(layerDirection)
                        offsetY = explosionOffset * math.sin(layerDirection)
                    elseif movementEffect == 9 then
                        -- Random Scatter Effect
                        local scatterRange = maximumOffset

                        -- Generate deterministic pseudo-random numbers based on 'i' and 'layer'
                        local function pseudoRandom(a, b)
                            return (math.sin(a * 12.9898 + b * 78.233) * 43758.5453) % 1
                        end

                        local randX = pseudoRandom(i, layer)
                        local randY = pseudoRandom(i + 1, layer + 1)

                        offsetX = (randX - 0.5) * scatterRange * separationFactor
                        offsetY = (randY - 0.5) * scatterRange * separationFactor
                    elseif movementEffect == 10 then
                        -- Circular Orbit Effect
                        local orbitRadius = maximumOffset
                        local angle = separationFactor * 2 * math.pi
                        offsetX = orbitRadius * math.cos(angle)
                        offsetY = orbitRadius * math.sin(angle)
                    elseif movementEffect == 11 then
                        -- Heartbeat Effect
                        local beatAmplitude = maximumOffset
                        local beatFrequency = 2
                        local beat = math.abs(math.sin(separationFactor * math.pi * beatFrequency))
                        offsetX = 0
                        offsetY = beatAmplitude * beat
                    elseif movementEffect == 12 then
                        -- Sine Wave Effect
                        local sineAmplitude = maximumOffset
                        local sineFrequency = 2
                        offsetX = separationFactor * maximumOffset
                        offsetY = sineAmplitude * math.sin(separationFactor * math.pi * sineFrequency)
                    elseif movementEffect == 13 then
                        -- Swirl Effect
                        local swirlTurns = 2 -- Number of swirl turns
                        local angle = separationFactor * swirlTurns * 2 * math.pi
                        offsetX = offsetDistance * math.cos(layerDirection + angle)
                        offsetY = offsetDistance * math.sin(layerDirection + angle)
                    elseif movementEffect == 14 then
                        -- Bounce Effect
                        local bounceAmplitude = maximumOffset
                        local bounceFrequency = 2
                        offsetX = 0
                        offsetY = math.abs(math.sin(separationFactor * math.pi * bounceFrequency)) * bounceAmplitude
                    elseif movementEffect == 15 then
                        -- Pulse Effect
                        local pulseSize = (1 + separationFactor * 1) * trail.originalSize
                        offsetX = 0
                        offsetY = 0
                        trail:SetSize(pulseSize, pulseSize)
                    elseif movementEffect == 16 then
                        -- Helix Effect
                        local helixTurns = 2
                        local angle = separationFactor * helixTurns * 2 * math.pi
                        offsetX = offsetDistance * math.cos(angle)
                        offsetY = offsetDistance * math.sin(angle) + separationFactor * (maximumOffset / 2) -- Adjust as needed
                    elseif movementEffect == 17 then
                        -- Firework Effect
                        local burstTime = 0.5
                        if separationFactor < burstTime then
                            offsetX = separationFactor * maximumOffset * math.cos(layerDirection)
                            offsetY = separationFactor * maximumOffset * math.sin(layerDirection)
                        else
                            offsetX = (1 - separationFactor) * maximumOffset * math.cos(layerDirection)
                            offsetY = (1 - separationFactor) * maximumOffset * math.sin(layerDirection)
                        end
                    elseif movementEffect == 18 then
                        -- Rain Effect
                        offsetX = 0
                        offsetY = -separationFactor * maximumOffset
                    elseif movementEffect == 19 then
                        -- Comet Effect
                        offsetX = -separationFactor * maximumOffset
                        offsetY = -separationFactor * maximumOffset
                    elseif movementEffect == 20 then
                        -- Galaxy Effect
                        local spiralTurns = 3
                        local angle = separationFactor * spiralTurns * 2 * math.pi
                        offsetX = offsetDistance * math.cos(angle)
                        offsetY = offsetDistance * math.sin(angle)
                    elseif movementEffect == 21 then
                        -- Twinkle Effect
                        trail:SetAlpha(math.random() * 0.5 + 0.5) -- Random alpha between 0.5 and 1
                        offsetX = 0
                        offsetY = 0
                    elseif movementEffect == 22 then
                        -- Flare Effect
                        offsetX = separationFactor * maximumOffset * math.cos(layerDirection)
                        offsetY = separationFactor * maximumOffset * math.sin(layerDirection)
                        trail:SetAlpha(1 - separationFactor)
                    elseif movementEffect == 23 then
                        -- Ripple Effect
                        local rippleSpeed = 2
                        local angle = layerDirection
                        offsetX = separationFactor * maximumOffset * math.cos(angle)
                        offsetY = separationFactor * maximumOffset * math.sin(angle)
                        trail:SetAlpha(1 - separationFactor)
                    elseif movementEffect == 24 then
                        -- Smoke Effect
                        offsetX = (math.random() - 0.5) * maximumOffset * separationFactor
                        offsetY = separationFactor * maximumOffset
                        trail:SetAlpha(1 - separationFactor)
                    elseif movementEffect == 25 then
                        -- Meteor Shower Effect
                        local meteorAngle = math.pi / 4  -- 45 degrees
                        offsetX = separationFactor * maximumOffset * math.cos(meteorAngle)
                        offsetY = -separationFactor * maximumOffset * math.sin(meteorAngle)
                    elseif movementEffect == 26 then
                        -- Pendulum Effect
                        local pendulumAmplitude = maximumOffset
                        local pendulumFrequency = 1
                        offsetX = pendulumAmplitude * math.sin(separationFactor * math.pi * pendulumFrequency)
                        offsetY = 0
                    elseif movementEffect == 27 then
                        -- DNA Strand Effect
                        local dnaTurns = 2
                        local angle = separationFactor * dnaTurns * 2 * math.pi
                        offsetX = maximumOffset * math.sin(angle)
                        offsetY = separationFactor * maximumOffset
                    elseif movementEffect == 28 then
                        -- Lightning Effect
                        offsetX = (math.random() - 0.5) * maximumOffset
                        offsetY = -separationFactor * maximumOffset
                    elseif movementEffect == 29 then
                        -- Orbiting Layers Effect
                        local orbitRadius = layer * (maximumOffset / EasyCursorTrailsDB.trailLayerCount)
                        local angle = separationFactor * 2 * math.pi
                        offsetX = orbitRadius * math.cos(angle)
                        offsetY = orbitRadius * math.sin(angle)
                    elseif movementEffect == 30 then
                        -- Waterfall Effect
                        offsetX = (math.random() - 0.5) * maximumOffset
                        offsetY = -layer * separationFactor * maximumOffset
                    elseif movementEffect == 31 then
                        -- Vortex Effect
                        local vortexTurns = 2
                        local angle = separationFactor * vortexTurns * 2 * math.pi
                        offsetX = offsetDistance * math.cos(angle)
                        offsetY = offsetDistance * math.sin(angle)
                    elseif movementEffect == 32 then
                        -- Tunnel Effect
                        offsetX = 0
                        offsetY = 0
                        local scale = 1 + separationFactor * 2
                        trail:SetScale(scale)
                    elseif movementEffect == 33 then
                        -- Strobe Effect
                        local strobeSpeed = 10
                        if math.floor(separationFactor * strobeSpeed) % 2 == 0 then
                            trail:Show()
                        else
                            trail:Hide()
                        end
                        offsetX = 0
                        offsetY = 0
                    elseif movementEffect == 34 then
                        -- Sunburst Effect
                        offsetX = separationFactor * maximumOffset * math.cos(layerDirection)
                        offsetY = separationFactor * maximumOffset * math.sin(layerDirection)
                        trail:SetAlpha(1 - separationFactor)
                    elseif movementEffect == 35 then
                        -- Fountain Effect
                        offsetX = (math.random() - 0.5) * maximumOffset * (1 - separationFactor)
                        offsetY = separationFactor * maximumOffset
                    elseif movementEffect == 36 then
                        -- Motion Blur Effect
                        local dx = cursorX - previousCursorX
                        local dy = cursorY - previousCursorY
                        local angle = math.atan2(dy, dx)
                        if dx == 0 and dy == 0 then
                            angle = 0
                        end
                        local stretchFactor = 1 + separationFactor * (maximumOffset / 6)
                        local originalSize = trail.originalSize or 32
                        local newWidth = originalSize
                        local newHeight = originalSize * stretchFactor
                        trail:SetSize(newWidth, newHeight)
                        if trail.texture and trail.texture.SetRotation then
                            trail.texture:SetRotation(angle)
                        end
                        offsetX = -separationFactor * dx * (maximumOffset / 6)
                        offsetY = -separationFactor * dy * (maximumOffset / 6)
                    elseif movementEffect == 37 then
                        -- Connected Glow Effect
                        local glowOffset = initialSeparation * 0.2 -- 20% of initialSeparation
                        offsetX = glowOffset * math.cos(layerDirection)
                        offsetY = glowOffset * math.sin(layerDirection)
                        trail:SetAlpha(0.8)
                        trail.texture:SetVertexColor(1, 1, 1, 0.8)
                    elseif movementEffect == 38 then
                        -- Burning Rocket Trail Effect
                        local divergence = (math.random() - 0.5) * (maximumOffset * 0.2)
                        offsetX = divergence
                        offsetY = separationFactor * maximumOffset * 1.5
                        trail:SetAlpha(1 - separationFactor)
                        trail.texture:SetVertexColor(1, 0.5, 0, 1 - separationFactor)
                        trail.texture:SetTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\Fire1.tga")
                        trail.texture:SetBlendMode("ADD")
                    elseif movementEffect == 39 then
                        -- Lightning Effect
                        local angleVariation = (math.random() - 0.5) * math.pi / 4
                        local baseAngle = layerDirection + angleVariation
                        offsetX = separationFactor * maximumOffset * math.cos(baseAngle)
                        offsetY = separationFactor * maximumOffset * math.sin(baseAngle)
                        trail:SetAlpha(0.9 - separationFactor * 0.4)
                        trail.texture:SetVertexColor(1, 1, 1, 0.9 - separationFactor * 0.4)
                        trail.texture:SetTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Bright_Dust.blp")
                        trail.texture:SetBlendMode("ADD")
                    elseif movementEffect == 40 then
                        -- Rain Effect
                        offsetX = 0
                        offsetY = separationFactor * maximumOffset * 2
                        trail:SetAlpha(0.7 - separationFactor * 0.3)
                        trail.texture:SetVertexColor(0.5, 0.7, 1, 0.7 - separationFactor * 0.3)
                        trail.texture:SetTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Nature\\rain.tga")
                        trail.texture:SetBlendMode("BLEND")
                    elseif movementEffect == 41 then
                        -- Fire Effect
                        local flicker = (math.random() - 0.5) * (maximumOffset * 0.1)
                        offsetX = flicker
                        offsetY = separationFactor * maximumOffset * 1.2
                        local red = 1
                        local green = math.random() * 0.5
                        local blue = 0
                        trail:SetAlpha(0.8 - separationFactor * 0.5)
                        trail.texture:SetVertexColor(red, green, blue, 0.8 - separationFactor * 0.5)
                        trail.texture:SetTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Magic\\Flames.blp")
                        trail.texture:SetBlendMode("ADD")
                        local scale = 1 + separationFactor * 0.5
                        trail:SetScale(scale)
                    elseif movementEffect == 42 then
                        -- Ghost Effect
                        local oscillation = math.sin(separationFactor * math.pi * 4) * (maximumOffset * 0.05)
                        offsetX = oscillation
                        offsetY = separationFactor * maximumOffset * 0.8
                        trail:SetAlpha(0.6 - separationFactor * 0.3)
                        trail.texture:SetVertexColor(0.7, 0.8, 1, 0.6 - separationFactor * 0.3)
                        trail.texture:SetTexture("Interface\\AddOns\\EasyCursorTrails\\Textures\\Trails\\Fantasy\\ghost.tga")
                        trail.texture:SetBlendMode("ADD")
                        local pulsate = 1 + 0.3 * math.sin(separationFactor * math.pi * 4)
                        trail:SetScale(pulsate)
                    else
                        -- Default to Linear Separation
                        offsetX = offsetDistance * math.cos(layerDirection)
                        offsetY = offsetDistance * math.sin(layerDirection)
                    end


                    -- Update trail position with offsets and user-defined offsets
                    trail:SetPoint("CENTER", UIParent, "BOTTOMLEFT",
                        pos.x + offsetX + (EasyCursorTrailsDB.trailOffsetX or 0),
                        pos.y + offsetY + (EasyCursorTrailsDB.trailOffsetY or 0)
                    )

                    -- Adjust trail alpha based on separation factor
                    if movementEffect < 36 or movementEffect > 42 then
                        local alpha = 1 - separationFactor
                        alpha = math.max(0, math.min(1, alpha))
                        trail:SetAlpha(alpha)
                    end

                    -- Show and apply color effects to the trail
                    trail:Show()
                    EasyCursorTrails.ApplyColorEffectTrail(trail, i)

                    -- Reset trail size and scale if necessary
                    if movementEffect ~= 32 and movementEffect ~= 36 and movementEffect ~= 41 and movementEffect ~= 42 then
                        trail:SetSize(trail.originalSize, trail.originalSize)
                        trail:SetScale(1)
                    end
                elseif trail then
                    trail:Hide()
                end
            end
        end

        -- Handle cursor stopping
        if EasyCursorTrails.cursorStopped then
            for i = 1, #EasyCursorTrails.cursorPositions do
                EasyCursorTrails.cursorPositions[i].x = cursorX
                EasyCursorTrails.cursorPositions[i].y = cursorY
            end
            EasyCursorTrails.cursorPositions = {}
            EasyCursorTrails.cursorStopped = false
        end
    else
        -- If trails are disabled, hide all trails and reset positions
        for _, layerPool in pairs(EasyCursorTrails.trailPool) do
            for _, trail in ipairs(layerPool) do
                trail:Hide()
            end
        end
        EasyCursorTrails.cursorPositions = {}
        EasyCursorTrails.previousCursorX, EasyCursorTrails.previousCursorY = cursorX, cursorY
        EasyCursorTrails.cursorStopped = false
    end
end

-- Create and set up the OnUpdate handler within EasyCursorTrails
EasyCursorTrails.updateFrame = CreateFrame("Frame")
EasyCursorTrails.updateFrame:SetScript("OnUpdate", function(self, elapsed)
    EasyCursorTrails.HandleTrailMovement(elapsed)
end)


function InitializeAddon()
    InitializeSavedVariables()
    InitializeSettingsMenu()
    EasyCursorTrails.colorIndexTrail = EasyCursorTrails.colorIndexTrail or 0
    EasyCursorTrails.InitializeCustomCursor()
    RebuildTrails()
    print("EasyCursorTrails loaded!")
end

local eventFrame=CreateFrame("Frame")
eventFrame:RegisterEvent("ADDON_LOADED")
eventFrame:SetScript("OnEvent", function(self, event, addonName)
    if event=="ADDON_LOADED" and addonName=="EasyCursorTrails" then
        InitializeAddon()
    end
end)

SLASH_EASYCURSORMENU1="/easymenu"
SlashCmdList["EASYCURSORMENU"]=function()
    local menu=_G["EasyCursorTrailsMenu"]
    if menu then
        menu:SetShown(not menu:IsShown())
    else
        print("EasyCursorTrails Error: Settings menu frame not found")
    end
end

--------------------------------
-- End of EasyCursorTrails.lua
--------------------------------
