--[[
	функции-помощники для скриптов уровня
]]

function log(str)
	print(str)
	io.flush()
end

local g_ThreadTable = {}
local g_RunningCoroutines = {}
local g_DeferredRunScripts = {}

local g_UniqueId = 0

local ResumeCoroutine = function(_num, ...)
	local info = g_ThreadTable[_num] 
	if (not info) or (not info.thread) then 
		Error("Trying to resume dead coroutine num ".._num) 
		return 
	end
	local status = coroutine.status(info.thread)
	if status~="dead" and (status~="normal" or info.start) then
		g_RunningCoroutines[#g_RunningCoroutines + 1] = _num
		info.start = false
		local success, error_str = coroutine.resume(info.thread, ...)
		if (not success) and error_str then
			Error(error_str.." thread status - "..coroutine.status(info.thread))
		end
		table.remove(g_RunningCoroutines)
	end
	
	status = coroutine.status(info.thread)
	if status=="dead" or status=="normal" then
		g_ThreadTable[_num].thread = nil
	end
end

function RunScript(_buffer)
	if not g_DeferredRunScripts then g_DeferredRunScripts = {} end
	g_DeferredRunScripts[#g_DeferredRunScripts + 1] = _buffer
end

function CreateScript(_funcname, ...)
	local new_thread = coroutine.create(
		function (...) 
			local chunk, err = loadstring(_funcname.."(...)")
			if chunk then chunk(...) else Error(err) end
		end
	)
	g_ThreadTable[#g_ThreadTable + 1] = { thread = new_thread, resume_time = 0, start = true, uid = g_UniqueId  }
	g_UniqueId = g_UniqueId + 1
	ResumeCoroutine(#g_ThreadTable, ...)
end

function Wait(_time) 
	if #g_RunningCoroutines==0 then Error("missing current coroutine") return end
	local thread_info = g_ThreadTable[g_RunningCoroutines[#g_RunningCoroutines]]
	if not thread_info then Error("Wait cant find lua coroutine")  return end 
	assert(thread_info.thread==coroutine.running())
	thread_info.resume_time = GetElapsedTime() + _time
	coroutine.yield() 
end

function ManageThreads()
	local level_time = GetElapsedTime()
	local i,t = nil,nil
	for i,t in ipairs(g_ThreadTable) do
		if t and t.thread then
			if t.resume_time <= level_time then ResumeCoroutine(i) end
		end
	end
	
	if g_DeferredRunScripts then
		for i,b in ipairs(g_DeferredRunScripts) do
			local new_thread = coroutine.create(
				function() 
					local chunk, err = loadstring(b) 
					if chunk then chunk() else Error(err) end 
				end
			)
			g_ThreadTable[#g_ThreadTable + 1] = { thread = new_thread, resume_time = 0, start = true, uid = g_UniqueId}
			g_UniqueId = g_UniqueId + 1
			ResumeCoroutine(#g_ThreadTable)
		end
	end
	g_DeferredRunScripts = nil
	
	local i = 1
	while i<=#g_ThreadTable do
		if not g_ThreadTable[i].thread then 
			table.remove(g_ThreadTable, i)
		else
			i = i + 1
		end
	end
end


function GetBrickUnion(id)
	local result = {}
	local union = g_Level.PrivateGetBrickUnion(id)
	local i,e = union.begin(), union._end()
	local count = 1
	while i~=e do
		result[count] = i.value
		i.inc(); count = count + 1
	end
	return result
end

function BrickUnionConnectFixed(union_id)
	local union = GetBrickUnion(union_id)
	local last_brick = nil
	for i,b in ipairs(union) do
		if last_brick then
			last_brick.ConnectFixed(b)
		end
		last_brick = b
	end
end

function BrickUnionConnect(union_id)
	local union = GetBrickUnion(union_id)
	local last_brick = nil
	for i,b in ipairs(union) do
		if last_brick then
			last_brick.Connect(b)
		end
		last_brick = b
	end
end
