local y={}local K=game:GetService("\072\097\112\116\105\099\083\101\114\118\105\099\101")local s=require(script:WaitForChild("\067\111\109\112\114\101\115\115\111\114"))local I=require(script:WaitForChild("\066\097\108\097\110\099\101"))local V={}local function G(y)local K=y or"\068\101\102\097\117\108\116"if not V[K]then V[K]={leftIntensity=0;rightIntensity=0;activeDelay=nil}end return V[K]end local function b()if K:IsMotorSupported(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Small)then K:SetMotor(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Small,0)end if K:IsMotorSupported(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Large)then K:SetMotor(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Large,0)end end local function R()local y=0 local s=0 for K,I in pairs(V)do if I.leftIntensity>y then y=I.leftIntensity end if I.rightIntensity>s then s=I.rightIntensity end end if y==0 and s==0 then b()else if K:IsMotorSupported(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Small)then K:SetMotor(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Small,y)end if K:IsMotorSupported(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Large)then K:SetMotor(Enum.UserInputType.Gamepad1,Enum.VibrationMotor.Large,s)end end end function y.Apply(r,y,K,V,b,m)local U=G(m)if U.activeDelay then task.cancel(U.activeDelay)U.activeDelay=nil end if not(y and(K and(V and V.Enabled)))then U.leftIntensity=0 U.rightIntensity=0 R()return end s:CompressAll(V)local M=(b or"\098\111\116\104"):lower()if V.Balance and V.Balance.Enabled then local K,s=I:Calculate(V,y,M)U.leftIntensity=K U.rightIntensity=s else local K=y local s=y if M=="\115"or M=="\115\109\097\108\108"then s=0 elseif M=="\108"or M=="\108\097\114\103\101"then K=0 end U.leftIntensity=K U.rightIntensity=s end R()U.activeDelay=task.delay(K,function()U.leftIntensity=0 U.rightIntensity=0 U.activeDelay=nil R()end)end function y.Stop(K,y)local s=V[y or"\068\101\102\097\117\108\116"]if s then if s.activeDelay then task.cancel(s.activeDelay)s.activeDelay=nil end s.leftIntensity=0 s.rightIntensity=0 end R()end function y.GetTotalIntensities(y)local K=0 local s=0 for y,I in pairs(V)do if I.leftIntensity>K then K=I.leftIntensity end if I.rightIntensity>s then s=I.rightIntensity end end return K,s end return y
local Modules = {}

local HapticService = game:GetService("HapticService")
local Compressor = require(script:WaitForChild("Compressor"))
local Balance = require(script:WaitForChild("Balance"))

local channels = {}

local function getChannel(name)
    local n = name or "Default"
    if not channels[n] then
        channels[n] = {
            leftIntensity = 0,
            rightIntensity = 0,
            activeDelay = nil
        }
    end
    return channels[n]
end

local function stopMotors()
    if HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small) then
        HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, 0)
    end
    if HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large) then
        HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large, 0)
    end
end

local function updateMotorsFromChannels()
    local maxLeft = 0
    local maxRight = 0
    for _, ch in pairs(channels) do
        if ch.leftIntensity > maxLeft then
            maxLeft = ch.leftIntensity
        end
        if ch.rightIntensity > maxRight then
            maxRight = ch.rightIntensity
        end
    end

    if maxLeft == 0 and maxRight == 0 then
        stopMotors()
    else
        if HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small) then
            HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Small, maxLeft)
        end
        if HapticService:IsMotorSupported(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large) then
            HapticService:SetMotor(Enum.UserInputType.Gamepad1, Enum.VibrationMotor.Large, maxRight)
        end
    end
end

function Modules:Apply(intensity, duration, settings, motorChoice, channelName)
    local ch = getChannel(channelName)
    if ch.activeDelay then
        task.cancel(ch.activeDelay)
        ch.activeDelay = nil
    end

    if not (intensity and duration and settings and settings.Enabled) then
        ch.leftIntensity = 0
        ch.rightIntensity = 0
        updateMotorsFromChannels()
        return
    end

    Compressor:CompressAll(settings)
    local c = (motorChoice or "both"):lower()

    if settings.Balance and settings.Balance.Enabled then
        local left, right = Balance:Calculate(settings, intensity, c)
        ch.leftIntensity = left
        ch.rightIntensity = right
    else
        local s = intensity
        local l = intensity
        if c == "s" or c == "small" then
            l = 0
        elseif c == "l" or c == "large" then
            s = 0
        end
        ch.leftIntensity = s
        ch.rightIntensity = l
    end

    updateMotorsFromChannels()

    ch.activeDelay = task.delay(duration, function()
        ch.leftIntensity = 0
        ch.rightIntensity = 0
        ch.activeDelay = nil
        updateMotorsFromChannels()
    end)
end

function Modules:Stop(channelName)
    local ch = channels[channelName or "Default"]
    if ch then
        if ch.activeDelay then
            task.cancel(ch.activeDelay)
            ch.activeDelay = nil
        end
        ch.leftIntensity = 0
        ch.rightIntensity = 0
    end
    updateMotorsFromChannels()
end



-- Experimental

function Modules:GetTotalIntensities()
    local maxLeft = 0
    local maxRight = 0
    for _, ch in pairs(channels) do
        if ch.leftIntensity > maxLeft then
            maxLeft = ch.leftIntensity
        end
        if ch.rightIntensity > maxRight then
            maxRight = ch.rightIntensity
        end
    end
    return maxLeft, maxRight
end

return Modules