size={1600,4096} 
-- include ("Custom Avionics/constants.lua")

-- RAIN
-- drefs
dr_f("DR_RAIN_PERCENT", "sim/weather/rain_percent")
dr_f("DR_PREC_ON_AC", "sim/weather/precipitation_on_aircraft_ratio")
dr_f("DR_AIRSPEED_KTS_PILOT", "sim/cockpit2/gauges/indicators/airspeed_kts_pilot")

dr_i("DR_SIM_PAUSED", "sim/time/paused")
dr_f("DR_VIEW_IS_OUTSIDE", "sim/graphics/view/view_is_external")
dr_f("DR_WIPER_ANGLE", "sim/flightmodel2/misc/wiper_angle_deg[0]")
Cdref("DR_RAIN_SPEED_PERCENT", "ksgy/L410/rain_speed_percent")
dr_i("DR_WIPER_ON", "sim/cockpit2/switches/wiper_speed") -- 0=off,1=25%speed,2=50%speed,3=100%speed.

Cdref("o1", "ksgy/ws/op1")
Cdref("o2", "ksgy/ws/op2")
-- dr_f("DR_WINDOW_HEAT_SWITCH", "")
-- dr_f("DR_FRAME_HEAT_SWITCH", "")
-- dr_f("DR_PROP_HEAT_SWITCH", "")

--anim constants
local MAX_RAINDROPS = 600                                    -- Max raindrops we show at heavy rain
local MAX_LIFETIME = 400                                     -- Max raindrop lifetime (frames) then it dies and gets replaced by a new drop
local VERTICAL_VECTOR_THRESHOLD = 15                         -- Vertical vector threshold for speed 0 to get drops going down (gravity)
local raindropsCount = (get(DR_PREC_ON_AC) + get(DR_RAIN_PERCENT)) * MAX_RAINDROPS          -- How many raindrops we show on a windshield per frame
local raindropsCountSparse = (get(DR_PREC_ON_AC) + get(DR_RAIN_PERCENT)) * MAX_RAINDROPS/3  -- How many raindrops we show on a windshield per frame (for small triangle window)

local raindropImages = {loadImage('raindrop2_NML.png')}
-- local windscreenWithRain = {loadImage('rain0.png'),loadImage('rain1.png'),loadImage('rain2.png')}
local windscreenWithRainWiper = {loadImage('rain0wiper.png'),loadImage('rain1wiper.png'),loadImage('rain2wiper.png')}

local windscreenWithRain = {loadImage('rain1.png'),loadImage('rain2.png'),loadImage('rain3.png'),loadImage('rain4.png'),loadImage('rain5.png'),loadImage('rain6.png')}
-- /RAIN

-- RANDOM HELPER
local A1, A2 = 727595, 798405  -- 5^17=D20*A1+A2
local D20, D40 = 1048576, 1099511627776  -- 2^20, 2^40
local X1, X2 = 0, 1
function rand()
    local U = X2*A2
    local V = (X1*A2 + X2*A1) % D20
    V = (V*D20 + U) % D40
    X1 = math.floor(V/D20)
    X2 = V - X1*D20
    return V/D40
end
-- RANDOM HELPER

dr_f("flight_time", "sim/time/total_flight_time_sec")
local elapsed = get(flight_time)
local currentRain = 0

changeBganimSpeed = (10 - get(DR_RAIN_PERCENT)*10) * 0.4
fadeSpeed = 0.2

-- TODO tresholdSec
function updateTimed(cb)
	changeBganimSpeed = (11 - get(DR_RAIN_PERCENT)*10) * 0.4

	if get(flight_time) > elapsed + changeBganimSpeed then 
		cb()
		elapsed = get(flight_time)
	end
end

function drawRainTexture()
	local op1 = (get(flight_time) - elapsed) / fadeSpeed
	local op2 = (changeBganimSpeed/fadeSpeed)- op1

	set(o1, op1)
	set(o2, op2)
	
	local idx1 = currentRain
	local idx2 = currentRain+1
	if (idx2 == 7) then idx2 = 1 end
	
	if (op2 < 1) then
		drawRotatedTexture(windscreenWithRain[idx1], 0, 1026, 1026, 1026, 1026, 1,1,1, op2)	
		drawRotatedTexture(windscreenWithRain[idx2], 0, 1026, 1026, 1026, 1026, 1,1,1, op1)	
	else
		drawRotatedTexture(windscreenWithRain[idx2], 0, 1026, 1026, 1026, 1026, 1,1,1, op1)	
		drawRotatedTexture(windscreenWithRain[idx1], 0, 1026, 1026, 1026, 1026, 1,1,1, op2)	
		
	end
end

function updateRainTexture()
	currentRain = math.floor(math.floor(rand() * 6) + 1)
end

--------------------------------------------------------------------------------

-- Returns a random image for the raindrop (red, green, blue boxes for now)
function getRaindropImage()
	return raindropImages[math.floor(math.floor(rand() * 3) + 1)]
end

-- Returns a random slide-slip (x movement) for a moving drop
function getRandomSideSlip(ret)
	-- local r = rand()
	-- if (r > 0.95) 
	-- 	ret = ret + rand()
	-- end
	-- if (r < 0.25) 
	-- 	ret = ret - rand()
	-- end

	return ret
end

-- Returns sideway movement based on spawn position - the closer to the edge, the likely to go sideways
function getSpeedAffection(drop, speedPercent)
	if (speedPercent < 0.1) then
		return 0
	end
    local dropSidewaysPositonRate = speedPercent * drop.spawn.x -- the less it is, the less sideways movement generated

	return (dropSidewaysPositonRate*dropSidewaysPositonRate)/80000
end

-- Returns rotation angle based on x and y vectors
function getDropProperties(x, y, speedPercent, drop)

	local width = drop.spawn.w + speedPercent * (speedPercent * speedPercent)*speedPercent*30
	local extraHeight = 0
	if (speedPercent > 0.25) then
		extraHeight = drop.lifetime2*2
	end
	local height = drop.spawn.h + speedPercent * (speedPercent * speedPercent)*speedPercent*100 + extraHeight

	local angle = (math.tan(x/y) / (math.pi / 180))*1.25
	local ret = (speedPercent*1.15) * angle
	if (ret > 90) then ret = 90 end

	return {
		angle=ret,
		w=width,
		h=height
	}
	
end

-- Returns drop physical properties
function getDropSpawnProps()
	local r = math.floor(math.floor(rand() * 8) + 3)
	return {
		w=r,
		h=r*2.5,
		opacity=0,
		wiped=false
	}
end

-- Creates a drop for the front windshield part
function createDropFront()
	-- windsheld front
	local bottomX = 1024
	local bottomY = 1644
	local topX = 1600
	local topY = 2040 


	local spawnX = math.floor(math.floor(rand() * topX) + bottomX)
	local spawnY = math.floor(math.floor(rand() * topY) + bottomY)

	local spawnProps = getDropSpawnProps()

	return {
		x=spawnX, -- TODO move under props
		y=spawnY, -- TODO move under props
		bottomX=bottomX,
		bottomY=bottomY,
		topX=topX,
		topY=topY,
		lifetime=math.floor(rand() * MAX_LIFETIME),
		lifetime2=0,
		props=spawnProps,
		img=getRaindropImage(),
		angle=0, -- TODO move under props
		spawn={
			x=spawnX,
			y=spawnY,
			w=spawnProps.w,
			h=spawnProps.h
		}
	}
end

-- Creates a drop for the side windshield part
function createDropSide()
	-- windsheld side
	local bottomX = 1024
	local bottomY = 1120
	local topX = 1600
	local topY = 1640 


	local spawnX = math.floor(math.floor(rand() * topX) + bottomX)
	local spawnY = math.floor(math.floor(rand() * topY) + bottomY)

	local spawnProps = getDropSpawnProps()

	return {
        x=spawnX, -- TODO move under props
        y=spawnY, -- TODO move under props
		bottomX=bottomX,
		bottomY=bottomY,
		topX=topX,
		topY=topY,
		lifetime= math.floor(rand() * MAX_LIFETIME),
		lifetime2=0,
		props=spawnProps,
		img=getRaindropImage(),
		angle=0,
		spawn={
			x=spawnX,
			y=spawnY,
			w=spawnProps.w,
			h=spawnProps.h
		}
	}
end

-- Creates a drop for the small triangle windshield part
function createDropTri()
	--windsheld triangle
	local bottomX = 1644
	local bottomY = 1644
	local topX = 2048
	local topY = 2000 


	local spawnX = math.floor(math.floor(rand() * topX) + bottomX)
	local spawnY = math.floor(math.floor(rand() * topY) + bottomY)

	local spawnProps = getDropSpawnProps()

	return {
        x=spawnX, -- TODO move under props
        y=spawnY, -- TODO move under props
		bottomX=bottomX,
		bottomY=bottomY,
		topX=topX,
		topY=topY,
		lifetime= math.floor(rand() * MAX_LIFETIME),
		lifetime2=0,
		props=spawnProps,
		img=getRaindropImage(),
		angle=0,
		spawn={
			x=spawnX,
			y=spawnY,
			w=spawnProps.w,
			h=spawnProps.h
		}
	}
end

-- Returns vertical velocity % based on speed: 0 (0%) -> 200 (100)
function getSpeedPercent(spd)
	return 100 * spd / 250
end

-- Sets drop velocity/movement properties based on environment, speed, position, etc...
function setDropVelocity(type, drop)
	-- allo gepnel y: ~-0.4, max speed y: ~5 kell legyen

	local spd = get(DR_AIRSPEED_KTS_PILOT) * 2 - 100
	local speedPercent = getSpeedPercent(get(DR_AIRSPEED_KTS_PILOT)) / 100
	local verticalVector = spd / VERTICAL_VECTOR_THRESHOLD -- * get(DR_RAIN_PERCENT) * (speedPercent+1)
	local random_speedup = 0

	local dropNewProps = getDropProperties(drop.x, drop.y, speedPercent, drop)

	drop.props.h = dropNewProps.h
	drop.props.w = dropNewProps.w

	if (get(DR_RAIN_PERCENT) > 0.25 and (drop.lifetime > 0 and drop.lifetime < 50) or (drop.lifetime > 75 and drop.lifetime < 175) or (drop.lifetime > 200 and drop.lifetime < 250) or (drop.lifetime > 250 and drop.lifetime < 275) or speedPercent > 0.2) then
		random_speedup = verticalVector/2 * (drop.props.h) / 60 -- random gyorsulasok a csurgasban
    else 
        drop.lifetime = drop.lifetime - get(DR_RAIN_PERCENT)+0.1
	end
	
	if (drop.props.wiped ~= true) then
		-- drop.props.opacity = (0.8-speedPercent/1.5)  -- sebesseggel halvanyulo csepp
		drop.props.opacity = 1  -- sebesseggel halvanyulo csepp
	end
	


	if (type == 'front') then
		drop.y = drop.y + random_speedup
		drop.x = getRandomSideSlip(drop.x) + getSpeedAffection(drop, speedPercent)
		drop.angle = dropNewProps.angle
	end

	if (type == 'tri') then
		drop.y = drop.y + random_speedup
		drop.x = getRandomSideSlip(drop.x) + getSpeedAffection(drop, speedPercent)
		drop.angle = dropNewProps.angle + 30
	end

	if (type == 'side') then
		drop.y = drop.y + random_speedup
		drop.x = getRandomSideSlip(drop.x) + getSpeedAffection(drop, speedPercent)*5
		drop.angle = dropNewProps.angle - 15
	end

	drop.lifetime = drop.lifetime + 1
	drop.lifetime2 = drop.lifetime2 + 1
end
-- Removes drops if wiper is on

function ptInTriangle(p, p0, p1, p2) 
    local A = 1/2 * (-p1.y * p2.x + p0.y * (-p1.x + p2.x) + p0.x * (p1.y - p2.y) + p1.x * p2.y)
    local sign
    
    if A < 0 then
    	sign = -1 
    else
    	sign = 1
    end

    local s = (p0.y * p2.x - p0.x * p2.y + (p2.y - p0.y) * p.x + (p0.x - p2.x) * p.y) * sign
    local t = (p0.x * p1.y - p0.y * p1.x + (p0.y - p1.y) * p.x + (p1.x - p0.x) * p.y) * sign
    
    return s > 0 and t > 0 and (s + t) < 2 * A * sign
end

function wipe(drop)
	if (get(DR_WIPER_ON) > 0) then
		local wiper_angle = (50 - get(DR_WIPER_ANGLE))*1.2
		local wiper_inner_arm_length = 200
		local wiper_outer_arm_length = 460 + (get(DR_WIPER_ANGLE)/50)*180

		local wiper_width = 5*get(DR_WIPER_ON)
		local xOffset = 1000
		local yOffset = 1620

		local D = {
			x=xOffset+math.cos(wiper_angle*math.pi/180) * wiper_inner_arm_length,
			y=yOffset+math.sin(wiper_angle*math.pi/180) * wiper_inner_arm_length
		}

		local A = {
			x=xOffset+math.cos(wiper_angle*math.pi/180) * wiper_outer_arm_length,
			y=yOffset+math.sin(wiper_angle*math.pi/180) * wiper_outer_arm_length
		}

		local C = {
			x=xOffset+math.cos((wiper_angle+wiper_width)*math.pi/180) * wiper_inner_arm_length,
			y=yOffset+math.sin((wiper_angle+wiper_width)*math.pi/180) * wiper_inner_arm_length
		}

		local B = {
			x=xOffset+math.cos((wiper_angle+wiper_width)*math.pi/180) * wiper_outer_arm_length,
			y=yOffset+math.sin((wiper_angle+wiper_width)*math.pi/180) * wiper_outer_arm_length
		}

		-- logDebug('wipe co2ord')
		-- logDebug(A.x, A.y, D.x, D.y, C.x, C.y, B.x, B.y)

		drawLine(A.x, A.y, B.x, B.y, 1, 1, 1, 1)
		drawLine(B.x, B.y, C.x, C.y, 1, 1, 1, 1)
		drawLine(C.x, C.y, D.x, D.y, 1, 1, 1, 1)
		drawLine(D.x, D.y, A.x, A.y, 1, 1, 1, 1)

		if (ptInTriangle(drop, D,A,B) or ptInTriangle(drop, D,B,C)) then
			-- drop.lifetime = MAX_LIFETIME + 1
			drop.props.opacity = 0
			drop.props.wiped = true
		end
	end
end


local rain1opacity = 0
local rain2opacity = 0
local rain3opacity = 0
local rainwiper1opacity = 0
local rainwiper2opacity = 0
local rainwiper3opacity = 0

local rain1opacity_ = 0
local rain2opacity_ = 0
local rain3opacity_ = 0
local rainwiper1opacity_ = 0
local rainwiper2opacity_ = 0
local rainwiper3opacity_ = 0

local opacityChangeValue

function drawWindShieldTexure()
	local speedPercent = getSpeedPercent(get(DR_AIRSPEED_KTS_PILOT)) / 50
	local wiperIsOn = get(DR_WIPER_ON) > 0
	opacityChangeValue = 0.005 + get(DR_WIPER_ON)/80

	if (wiperIsOn == true) then
		rain1opacity = 0
		rain2opacity = 0
		rain3opacity = 0
	
		rainwiper1opacity = 0.66-speedPercent
	
		if (speedPercent <= 0.5) then
			rainwiper2opacity = speedPercent*2
		end

		if (speedPercent > 0.5) then
			rainwiper2opacity = (1-speedPercent)*2
		end
		
		rainwiper3opacity = (speedPercent-0.5)*2		
		

	else
		rainwiper1opacity = 0
		rainwiper2opacity = 0
		rainwiper3opacity = 0
	
		rain1opacity = 0.66-speedPercent
	
		if (speedPercent <= 0.5) then
			rain2opacity = speedPercent*2
		end

		if (speedPercent > 0.5) then
			rain2opacity = (1-speedPercent)*2
		end
		
		rain3opacity = (speedPercent-0.5)*2
	end

	
	if (rain1opacity_ >= rain1opacity) then
		rain1opacity_ = rain1opacity_ - opacityChangeValue
	else
		rain1opacity_ = rain1opacity_ + opacityChangeValue
	end
	if (rain2opacity_ >= rain2opacity) then
		rain2opacity_ = rain2opacity_ - opacityChangeValue
	else
		rain2opacity_ = rain2opacity_ + opacityChangeValue
	end
	if (rain3opacity_ >= rain3opacity) then
		rain3opacity_ = rain3opacity_ - opacityChangeValue
	else
		rain3opacity_ = rain3opacity_ + opacityChangeValue
	end
	
	if (rainwiper1opacity_ < rainwiper1opacity) then
		rainwiper1opacity_ = rainwiper1opacity_ + opacityChangeValue
	else
		rainwiper1opacity_ = rainwiper1opacity_ - opacityChangeValue
	end
	if (rainwiper2opacity_ < rainwiper2opacity) then
		rainwiper2opacity_ = rainwiper2opacity_ + opacityChangeValue
	else
		rainwiper2opacity_ = rainwiper2opacity_ - opacityChangeValue
	end
	if (rainwiper3opacity_ < rainwiper3opacity) then
		rainwiper3opacity_ = rainwiper3opacity_ + opacityChangeValue
	else
		rainwiper3opacity_ = rainwiper3opacity_ - opacityChangeValue
	end

--	logDebug(rain1opacity_)

	if (get(DR_RAIN_PERCENT) > 0) then
		-- drawRotatedTexture(windscreenWithRain[1], 0, 1026, 1026, 1026, 1026, 1,1,1, rain1opacity_)
		-- drawRotatedTexture(windscreenWithRain[2], 0, 1026, 1026, 1026, 1026, 1,1,1, rain2opacity_)
		-- drawRotatedTexture(windscreenWithRain[3], 0, 1026, 1026, 1026, 1026, 1,1,1, rain3opacity_)
		-- drawRotatedTexture(windscreenWithRainWiper[1], 0, 1026, 1026, 1026, 1026, 1,1,1, rainwiper1opacity_)
		-- drawRotatedTexture(windscreenWithRainWiper[2], 0, 1026, 1026, 1026, 1026, 1,1,1, rainwiper2opacity_)
		-- drawRotatedTexture(windscreenWithRainWiper[3], 0, 1026, 1026, 1026, 1026, 1,1,1, rainwiper3opacity_)
	end
end


-- Set up initial drops
local frontDrops = {}
local triDrops = {}
local sideDrops = {}

for z = 0, MAX_RAINDROPS do
	frontDrops[z] = createDropFront()
end

-- Side windows needs less raindrops
for zz = 0, MAX_RAINDROPS/3 do
	triDrops[zz] = createDropTri()
	sideDrops[zz] = createDropSide()
end

function update()

	local speedPercent = getSpeedPercent(get(DR_AIRSPEED_KTS_PILOT)) / 100
	-- set(DR_RAIN_SPEED_PERCENT, 0)
	-- set(DR_RAIN_PERCENT, 1) -- DEBUG
	raindropsCount = get(DR_RAIN_PERCENT) * MAX_RAINDROPS
	raindropsCountSparse = get(DR_RAIN_PERCENT) * MAX_RAINDROPS / 3

	if (get(DR_SIM_PAUSED) == 1 or get(DR_VIEW_IS_OUTSIDE) == 1 or get(DR_RAIN_PERCENT) == 0) then
		return
	end
	for i = 0, raindropsCount do
		setDropVelocity('front', frontDrops[i])
		wipe(frontDrops[i])
	end
	for j = 0, raindropsCountSparse do
		setDropVelocity('tri', triDrops[j])
		setDropVelocity('side', sideDrops[j])
	end

	-- logDebug(get(DR_AIRSPEED_KTS_PILOT))

	
	-- TODO updateTimed(getRainPercent, 0.25)
	-- TODO die raindrops, if rain_percent changes
	
end

function draw()

	-- updateTimed(updateRainTexture)
	-- drawRainTexture()

	if (get(DR_SIM_PAUSED) == 1 or get(DR_VIEW_IS_OUTSIDE) == 1 or get(DR_RAIN_PERCENT) == 0) then
		return
	end
	
	-- drawWindShieldTexure()
	
	for i = 0, raindropsCount do
		-- front window
		if (frontDrops[i].y < frontDrops[i].bottomY or frontDrops[i].y > frontDrops[i].topY or frontDrops[i].x > frontDrops[i].topX or frontDrops[i].lifetime > MAX_LIFETIME) then
			frontDrops[i] = createDropFront()
		else 
			-- wipe(frontDrops[i])
			drawRotatedTexture(frontDrops[i].img, frontDrops[i].angle, frontDrops[i].x, frontDrops[i].y, frontDrops[i].props.w, frontDrops[i].props.h, 1,1,1, frontDrops[i].props.opacity)
		end
	end

	for j = 0, raindropsCountSparse do

		-- side window
		if (sideDrops[j].y < sideDrops[j].bottomY or sideDrops[j].y > sideDrops[j].topY or sideDrops[j].x > sideDrops[j].topX or sideDrops[j].lifetime > MAX_LIFETIME) then
			sideDrops[j] = createDropSide()
		else 
			drawRotatedTexture(sideDrops[j].img, sideDrops[j].angle, sideDrops[j].x, sideDrops[j].y, sideDrops[j].props.w, sideDrops[j].props.h, 1,1,1, sideDrops[j].props.opacity)

		end

		-- -- triangle window
		if ( triDrops[j].y < triDrops[j].bottomY or triDrops[j].y > triDrops[j].topY or triDrops[j].x > triDrops[j].topX or triDrops[j].lifetime > MAX_LIFETIME)  then
			triDrops[j] = createDropTri()
		else 
			drawRotatedTexture(triDrops[j].img, triDrops[j].angle, triDrops[j].x, triDrops[j].y, triDrops[j].props.w, triDrops[j].props.h, 1,1,1, triDrops[j].props.opacity)
		end
	end
end

