local ent = ent
local scene = entities.currentScene()
local controller = entities.controller()
local controllerTransform = controller:getComponent("Transform")
local timer = Timer.new()
if not timer:running() then timer:start() end

local metadata = ent:getComponent("Metadata")
local transform = ent:getComponent("Transform")
local physicsState = ent:getComponent("PhysicsState")

local soundEmitter = ent --ent:loadChild("/sound.json",true)
local playSound = function( key )
	if not loop then loop = false end
	local url = "./audio/sfx/" .. key .. ".ogg"
	soundEmitter:queueHook("sound:Emit.%UID%", {
		filename = string.resolveURI(url, metadata["system"]["root"]),
		spatial = true,
		loop = loop,
		volume = "sfx",
		streamed = true
	}, 0)
end
local playSoundscape = function( key )
	local url = "./audio/soundscape/" .. key .. ".ogg"
	soundEmitter:queueHook("sound:Emit.%UID%", {
		filename = string.resolveURI(url, metadata["system"]["root"]),
		spatial = false,
		volume = "sfx",
		loop = true,
		streamed = true
	}, 0)
end
local stopSoundscape = function( key )
	local url = "./audio/soundscape/" .. key .. ".ogg"
	soundEmitter:queueHook("sound:Stop.%UID%", {
		filename = string.resolveURI(url, metadata["system"]["root"])
	}, 0)
end

local target = Vector3f(0,0,0)
local speed = metadata["speed"] or 1.0 / 3.0
local angle = metadata["angle"] or 1.5
transform.orientation = Quaternion.axisAngle( Vector3f(0,1,0), 1.5 )
local starting = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), -angle ))
local ending = transform.orientation:multiply(Quaternion.axisAngle( Vector3f(0,1,0), angle ))
-- on tick
local delta = 0
local watch = 0
local alerted = false
local light = nil
local lightOffset = nil

for k, v in pairs(ent:getChildren()) do
	if v:uid() ~= soundEmitter:uid() then
		light = v
		local transform = v:getComponent("Transform")
		lightOffset = Vector3f(transform.position) --:magnitude()
	end
end

ent:bind( "tick", function(self)
	soundEmitter:getComponent("Transform").position = transform.position

	local angleThreshold = metadata["sensitivity"] or 20

	local lightTransform = light and light:getComponent("Transform") or nil
	local lightMetadata = light and light:getComponent("Metadata") or {}
	if lightTransform ~= nil then
		lightTransform.position = transform.orientation:rotate( lightOffset );
		if lightMetadata and lightMetadata["light"] and lightMetadata["light"]["static"] then
			lightTransform.position = lightTransform.position + transform.position
		end
	end

	local controllerPosition = Vector3f(controllerTransform.position.x, 0, controllerTransform.position.z)
	local cameraPosition = Vector3f(transform.position.x, 0, transform.position.z)
	local distance = cameraPosition:distance(controllerPosition)
	local direction = cameraPosition - controllerPosition
	local angle = math.acos(transform.orientation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926
	if angle < angleThreshold and distance < 16 then
		if watch == 0 then
			watch = 6
			playSound("camera_see")
			if light then
				light:callHook( "object:UpdateMetadata.%UID%", {
					path = "light.color",
					value = {
						[1] = 1,
						[2] = 1,
						[3] = 0
					}
				} )
			end
		end
		watch = watch + time.delta()
		if watch > 12 and not alerted then
			playSound("camera_alert")
			playSound("xerxes_alert")
			playSoundscape("alarm")
			alerted = true
			timer:reset()
			if light then
				light:callHook( "object:UpdateMetadata.%UID%", {
					path = "light.color",
					value = {
						[1] = 1,
						[2] = 0,
						[3] = 0
					}
				} )
				light:callHook( "object:UpdateMetadata.%UID%", {
					path = "light.fade",
					value = {
						rate = 1,
						power = 0.01,
						timeout= 0.5
					}
				} )
			end
		end
	else
		if watch > 0 and not alerted then
			watch = watch - time.delta()
			if watch < 0 then
				io.print("CAMERA LOST")
				watch = 0
				speed = metadata["speed"] or 1.0 / 3.0
				if light then
					light:callHook( "object:UpdateMetadata.%UID%", {
						path = "light.color",
						value = {
							[1] = 0,
							[2] = 1,
							[3] = 0
						}
					} )
					light:callHook( "object:UpdateMetadata.%UID%", {
						path = "light.fade",
						value = nil
					} )
				end
			end
		end
	end
	if not alerted and watch > 0 and light then
		light:callHook( "object:UpdateMetadata.%UID%", {
			path = "light.fade.rate",
			value = math.floor(watch / 2),
		} )
		light:callHook( "object:UpdateMetadata.%UID%", {
			path = "light.fade.power",
			value = 0.01,
		} )
		light:callHook( "object:UpdateMetadata.%UID%", {
			path = "light.fade.timeout",
			value = 0.5,
		} )
	end
	if alerted and timer:elapsed() >= 60 then
		timer:reset()
		alerted = false
		watch = 0
		io.print("ALERT OVER")
		playSound("camera_lost")
		stopSoundscape("alarm");
		if light then
			light:callHook( "object:UpdateMetadata.%UID%", {
				path = "light.color",
				value = {
					[1] = 0,
					[2] = 1,
					[3] = 0
				}
			} )
			light:callHook( "object:UpdateMetadata.%UID%", {
				path = "light.fade",
				value = nil
			} )
		end
	end
	
	delta = delta + time.delta() * speed
	local nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 )
--[[
	-- stop if we are going to look away from player
	local angleNext = math.acos(nextRotation:rotate( Vector3f(0,0,1):normalize() ):dot( direction:normalize() )) * 180.0 / 3.1415926
	if watch > 0 and angleNext > angle then
		delta = delta - time.delta() * speed * 3
		nextRotation = starting:slerp( ending, math.cos(delta) * 0.5 + 0.5 )
	end
]]
	transform.orientation = nextRotation
end )