--APPEARANCE

local RainThickness = 0.1 --Thickness of the rain drops in studs
local RainLength = 5 --Length of the rain drop in studs
local RainTransparency = 0.8 --Transparency of the rain
local TrailPerPart = 4 --Amount of trails adorned to one part
local TrailPartRadius = 10 --Max radius from the part a trail can be adorned
local TrailYOffset = 20 --Max Y offset a trail can have





local RainParent = Instance.new("Folder")
RainParent.Name = "Rain"
RainParent.Parent = game.Workspace.CurrentCamera

local RainPart = Instance.new("Part")
RainPart.Transparency = 1
RainPart.Size = Vector3.new(0.2,0.2,0.2)
RainPart.Anchored = true
RainPart.CanCollide = false
RainPart.TopSurface = "Smooth"
RainPart.BottomSurface = "Smooth"

local function AdornRandomTrailToPart()
	local RandomCenterX,RandomCenterZ = math.random(-TrailPartRadius,TrailPartRadius),math.random(-TrailPartRadius,TrailPartRadius)
	local YOffset = math.random(0,TrailYOffset)
	local Attahcment1 = Instance.new("Attachment")
	Attahcment1.Position = Vector3.new(RandomCenterX - RainThickness/2,YOffset,RandomCenterZ)
	Attahcment1.Parent = RainPart
	
	local Attahcment2 = Instance.new("Attachment")
	Attahcment2.Position = Vector3.new(RandomCenterX + RainThickness/2,YOffset,RandomCenterZ)
	Attahcment2.Parent = RainPart
	
	local Trail = Instance.new("Trail")
	Trail.Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0,RainTransparency,0),NumberSequenceKeypoint.new(1,1)})
	Trail.Attachment0 = Attahcment1
	Trail.Attachment1 = Attahcment2
	Trail.Lifetime = RainLength/RainFallSpeed
	Trail.Parent = RainPart
end

for _ = 1, TrailPerPart do
	AdornRandomTrailToPart()
end



local Camera = game.Workspace.CurrentCamera
local RenderStepped = game:GetService("RunService").RenderStepped

local RainRadiusDiv2 = RainRadius/2
local RainPartClone = RainPart.Clone
local CFramenew,CFrameAngles = CFrame.new,CFrame.Angles
local random = math.random
local RenderSteppedConnect = RenderStepped.Connect

local RainAPI = {}
local OverridenRegions = {}
local CurrentOverrideId = 0
local CurrentCreateEvent

local function CreateRainDrop(StartX,StartY,StartZ,EndX,EndY,EndZ,Rotation)
	local StartCF,EndCF = CFramenew(StartX,StartY,StartZ) * Rotation,CFramenew(EndX,EndY,EndZ) * Rotation
	local LerpFunction = StartCF.lerp
	
	local function GetCFrame(Alpha)
		return LerpFunction(StartCF,EndCF,Alpha)
	end
	
	local NewDrop = RainPartClone(RainPart)
	NewDrop.CFrame = StartCF
	NewDrop.Parent = RainParent
	
	local FallTime = (StartY - EndY)/RainFallSpeed
	local StartTime = tick()
	local RenderSteppedEvent
	RenderSteppedEvent = RenderSteppedConnect(RenderStepped,function()
		local Alpha = (tick() - StartTime)/FallTime
		if Alpha > 1 then
			NewDrop:Destroy()
			RenderSteppedEvent:disconnect()
		else
			NewDrop.CFrame = GetCFrame(Alpha)
		end
	end)
end

local function SpawnRainDrop(CenterX,CenterZ)
	local X,Z = CenterX + random(-RainRadiusDiv2,RainRadiusDiv2),CenterZ + random(-RainRadiusDiv2,RainRadiusDiv2)
	local StartY,EndY = StartY,DefaultEndY
	
	for i = 1, #OverridenRegions do
		local RegionData = OverridenRegions[i]
		if X > RegionData[1] and Z > RegionData[2] and X < RegionData[3] and Z < RegionData[4] then
			EndY = RegionData[5]
			break
		end
	end
	
	local FallTime = (StartY - EndY)/RainFallSpeed
	local WindOffsetX,WindOffsetZ = (FallTime * WindSpeedX)/2,(FallTime * WindSpeedZ)/2
	CreateRainDrop(X - WindOffsetX,StartY,Z - WindOffsetZ,X + WindOffsetX,EndY,Z + WindOffsetZ,CFrameAngles(0,random(),0))
end


local function StopRain()
	if CurrentCreateEvent then CurrentCreateEvent:Disconnect() end
end

local function StartRain()
	StopRain()
	CurrentCreateEvent = RenderSteppedConnect(RenderStepped,function(Delta)
		local CameraPosition = Camera.CFrame.p
		local X,Z = CameraPosition.X,CameraPosition.Z
		for _ = 1, RainGroupsPerSecond * Delta do
			SpawnRainDrop(X,Z)
		end
	end)
end





function RainAPI:AddOverrideRegion(X1,Z1,X2,Z2,OverrideY)
	CurrentOverrideId = CurrentOverrideId + 1
	local Id = CurrentOverrideId
	
	table.insert(OverridenRegions,{X1 - TrailPartRadius,Z1 - TrailPartRadius,X2 + TrailPartRadius,Z2 + TrailPartRadius,OverrideY,Id})
	return Id
end

function RainAPI:RemoveOverrideRegion(Id)
	for i,RegionData in pairs(OverridenRegions) do
		if RegionData[6] == i  then
			table.remove(OverridenRegions,i)
		end
	end
end

function RainAPI:StartRain()
	StartRain()
end

function RainAPI:StopRain()
	StopRain()
end

function RainAPI:SetWindSpeed(X,Z)
	WindSpeedX = X
	WindSpeedZ = Z
end

function RainAPI:GetWindSpeed()
	return WindSpeedX,WindSpeedZ
end

function RainAPI:SetRainGroupsPerSecond(NewRainGroupsPerSecond)
	RainGroupsPerSecond = NewRainGroupsPerSecond
end

function RainAPI:GetRainGroupsPerSecond()
	return RainGroupsPerSecond
end

return RainAPI
