#include "script/common.lua"

CONNECTION_DIST = 50
MAX_DIST = 60

connectionTimer = 0

gReceiverShape = nil
gReceiverLocalPos = nil

gTransmitterShape = nil
gTransmitterLocalPos = nil

function init()
	broken = false
	target = FindBody("target")
	

	local recvPos = GetLocationTransform(FindLocation("receiver", true)).pos
	gReceiverShape = FindShape("receiver", true)
	gReceiverLocalPos = TransformToLocalPoint(GetShapeWorldTransform(gReceiverShape), recvPos)

	local txPos = GetLocationTransform(FindLocation("transmitter")).pos
	gTransmitterShape = FindShape("transmitter")
	gTransmitterLocalPos = TransformToLocalPoint(GetShapeWorldTransform(gTransmitterShape), txPos)

	rayOffset = {}
	rayOffset[1] = Vec(-0.15, 0, 0)
	rayOffset[2] = Vec(0.15, 0, 0)
	rayOffset[3] = Vec(0, -0.15, 0)
	rayOffset[4] = Vec(0, 0.15, 0)
	rayOffset[5] = Vec(0, 0, -0.15)
	rayOffset[6] = Vec(0, 0, 0.15)
	rayOffset[7] = Vec(0, 0, 0)
end

function RadiolinkCheckConnectionLUA(receiverPos, transmitterPos, receiverShape, transmitterShape)
	local connection = false
	local dir = VecSub(receiverPos, transmitterPos)
	local length = VecLength(dir)
	if length > 0 then
		dir = VecScale(dir, 1.0/length)
		QueryRejectShape(receiverShape)
		QueryRejectShape(transmitterShape)
		QueryRequire("physical")
		connection = false
		for i=1,#rayOffset do
			local probe = VecAdd(transmitterPos, rayOffset[i])
			if not QueryRaycast(probe, dir, length, 0, true) then
				connection = true
			else
			end
		end
	end
	
	return connection,dir,length
end

function RadiolinkDrawLinesLUA(radius, length, dir, transmitterPos, receiverPos, connTimer, r, g, b, alpha)
	local perp1 = VecNormalize(VecCross(dir, Vec(0, 1, 0)))
	local perp2 = VecNormalize(VecCross(dir, perp1))
	local steps = math.floor(length / 0.25)
	steps = math.max(steps, 3)
	local t = -GetTime() * 20
	local p0 = transmitterPos
	for i=1, steps-1 do
		local q = (i+1)/steps
		local p1 = VecLerp(transmitterPos, receiverPos, q)
		local a1 = (t + q * length * 5)
		local r1 = math.sin(q*math.pi)*radius * connTimer
		p1 = VecAdd(p1, VecScale(perp1, math.sin(a1)*r1))
		p1 = VecAdd(p1, VecScale(perp2, math.cos(a1)*r1))
		DrawLine(p0, p1, r, g, b, alpha)
		p0 = p1
	end
end

function tick(dt)
	if broken then 
		return
	end

	local receiverPos = TransformToParentPoint(GetShapeWorldTransform(gReceiverShape), gReceiverLocalPos)
	local transmitterPos = TransformToParentPoint(GetShapeWorldTransform(gTransmitterShape), gTransmitterLocalPos)

	--local connection, dir, length = RadiolinkCheckConnectionLUA(receiverPos, transmitterPos, gReceiverShape, gTransmitterShape)
	local connection, dir, length = RadiolinkCheckConnectionCPP(receiverPos, transmitterPos, gReceiverShape, gTransmitterShape)
	
	local connectionOk = false
	if connection then
		local alpha
		local radius = 0.1
		local r,g,b = 0,0,0
		if length > CONNECTION_DIST then
			radius = radius * 0.1
			alpha = (1.0 - (length-CONNECTION_DIST)/(MAX_DIST-CONNECTION_DIST)) * 0.5
			if math.random(1, 10) < 5 then
				alpha = alpha * 0.5
			end
			r = 1
			g = 0.7
			b = 0.7
		else
			connectionOk = true
			alpha = math.max(1 * connectionTimer , (1.0 - (length-CONNECTION_DIST)/(MAX_DIST-CONNECTION_DIST)) * 0.5)
			if connectionTimer > 0.95 then
				r = 0.7 
				g = 1
				b = 0.7
			else
				r = 1
				g = 0.7
				b = 0.7
			end
		end
		
		--RadiolinkDrawLinesLUA(radius, length, dir, transmitterPos, receiverPos, connectionTimer, r, g, b, alpha)
		RadiolinkDrawLinesCPP(radius, length, dir, transmitterPos, receiverPos, connectionTimer, r, g, b, alpha)
	end
	
	if connectionOk then
		connectionTimer = connectionTimer + dt

		if connectionTimer > 1 then
			connectionTimer = 1
			SetTag(target, "target", "ok")
		end
	else
		connectionTimer = 0
		SetTag(target, "target", "custom")
	end
end

