#include "script/common.lua"

min_cooldown = GetIntParam("MinTornadoDelay", 15)
max_cooldown = GetIntParam("MaxTornadoDelay", 35)

local MIN_RADIUS = 0.3
local MAX_RADIUS = 8
local ROT_SPEED = 5
local HEIGHT = 30
local MIN_SPAWN_DIST_TO_PLAYER = 10

local SUCK_RADIUS = 20

local randomtry = 0
local randomtime = 0
local allowtornadospawn = true

goforward = false

function rnd(mi, ma)
	return math.random(1000)/1000*(ma-mi) + mi
end

function rndVec(t)
	return Vec(rnd(-t, t), rnd(-t, t), rnd(-t, t))
end

tornado = {}
tornado.pos = Vec()
tornado.age = 0
tornado.lifetime = 0
tornado.spawnAngle = 0
tornado.active = false

local tornadostartpos = nil
local tornadoendpos = nil
starttornado = GetBoolParam("StartTornado", true)

function init()
	tornadoSnd = LoadLoop("tornado.ogg")
	
	--- Tornado triggers and cooldowns-----
	triggers = FindTriggers()
	trigger_cooldown = {}	
	for i = 1, #triggers do
		SetTag(triggers[i], "id", tostring(i))
		trigger_cooldown[i] = 0
	end
	---------------------------------------
	
	tornadostartpos = FindLocation("start")
	tornadoendpos = FindLocation("finish")	
end

function spawn(startPos, endPos, lifetime)
	tornado.startPos = startPos
	tornado.endPos = endPos
	tornado.age = 0
	tornado.lifetime = lifetime
	tornado.spawnAngle = 0
	tornado.pos = startPos
	tornado.active = true
end

function mix(lo, hi, t)
	return lo+(hi-lo)*t
end

function getOffset(relativeHeight)
	local bigAng = tornado.age * 1 + relativeHeight*8
	local bend = math.sin(relativeHeight*math.pi) * 3 -- Bend only in the middle
	return Vec(math.sin(bigAng)*bend, 0, math.sin(bigAng*0.7)*bend)
end

function emitParticles()
	tornado.spawnAngle = tornado.spawnAngle + 2.39996
	TornadoSpawnParticlesCPP(tornado.spawnAngle, HEIGHT, MIN_RADIUS, MAX_RADIUS, ROT_SPEED, tornado.pos, tornado.amount, tornado.age)
end

function getVelForBody(pos, mass, vel, angVel)
	--Closest point on tornado
	local tornadoPoint = VecCopy(tornado.pos)
	tornadoPoint[2] = pos[2]
	local tornadoHeight = clamp((tornadoPoint[2] - tornado.pos[2])/HEIGHT, 0.0, 1.0)
	tornadoPoint = VecAdd(tornadoPoint, getOffset(tornadoHeight))
	
	local toTornado = VecSub(tornadoPoint, pos)
	local dist = VecLength(toTornado)
	if dist > 0.0 then
		toTornado = VecScale(toTornado, 1.0 / dist)
	end
	
	if dist < SUCK_RADIUS then
		local strength = 1.0 - dist/SUCK_RADIUS
		strength = strength * (1-tornadoHeight) 
		strength = strength * strength
		strength = strength * 3.0 * tornado.amount
		strength = strength * 1000 / (1000+mass)
		
		local addVel = VecScale(toTornado, strength)
		addVel[2] = strength * 0.5
		local perp = Vec(toTornado[3], 0.0, -toTornado[1])
		addVel = VecAdd(addVel, VecScale(perp, strength*0.2))
		local maxVel = 8
		
		for i=1, 3 do
			if addVel[i] < 0 and vel[i] < -maxVel then addVel[i]=0 end
			if addVel[i] > 0 and vel[i] > maxVel then addVel[i]=0 end
		end

		local maxAngVel = 5
		local addAngVel = -ROT_SPEED * strength * 0.05
		if angVel[2] < -maxAngVel then addAngVel = 0 end
		return VecAdd(vel, addVel), VecAdd(angVel, Vec(0, addAngVel, 0))
	else 
		return vel, angVel
	end
end



function update(dt)
	for i = 1, #trigger_cooldown do
		if trigger_cooldown[i] > 0 then
			trigger_cooldown[i] = trigger_cooldown[i] - dt 
		end
	end
	if starttornado then
		if goforward then
			spawn(GetLocationTransform(tornadoendpos).pos, GetLocationTransform(tornadostartpos).pos, 10)
		else
			spawn(GetLocationTransform(tornadostartpos).pos, GetLocationTransform(tornadoendpos).pos, 10)
		end
		goforward = not goforward
		starttornado = false
	end
	
	if allowtornadospawn then
		if tornado.active then
			tornado.pos = VecLerp(tornado.startPos, tornado.endPos, tornado.age/tornado.lifetime)
			local fadeIn = 3
			local fadeOut = 3
			if tornado.age < fadeIn	then 
				tornado.amount = tornado.age/fadeIn
			elseif tornado.lifetime-tornado.age < fadeOut then
				tornado.amount = (tornado.lifetime-tornado.age)/fadeOut
			else
				tornado.amount = 1.0
			end
			tornado.amount = tornado.amount * tornado.amount
			PlayLoop(tornadoSnd, tornado.pos, tornado.amount * 3)
		
			tornado.pos[1] = tornado.pos[1] + 0.03
			tornado.pos[3] = tornado.pos[3] + 0.03
			emitParticles()
			tornado.age = tornado.age + dt
			if tornado.age >= tornado.lifetime then
				starttornado = true
			end
		end
	else
		randomtime = randomtime + dt
		if randomtime > 1 then
			--math.randomseed(GetScriptId())
			local rollthedice = math.random(3)
			if rollthedice > 2 then
				allowtornadospawn = true
			else
				randomtry = randomtry + 1
				randomtime = 0
			end
			if randomtry > 2 then
				allowtornadospawn = true
			end
		end		
	end
end